~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/******************************************************
 
19
/**************************************************//**
 
20
@file row/row0mysql.c
20
21
Interface between Innobase row operations and MySQL.
21
22
Contains also create table and other data dictionary operations.
22
23
 
30
31
#endif
31
32
 
32
33
#include "row0ins.h"
 
34
#include "row0merge.h"
33
35
#include "row0sel.h"
34
36
#include "row0upd.h"
35
37
#include "row0row.h"
50
52
#include "fil0fil.h"
51
53
#include "ibuf0ibuf.h"
52
54
 
53
 
/* 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 */
54
58
UNIV_INTERN ibool       row_rollback_on_timeout = FALSE;
55
59
 
56
 
/* List of tables we should drop in background. ALTER TABLE in MySQL requires
57
 
that the table handler can drop the table in background when there are no
58
 
queries to it any more. Protected by the kernel mutex. */
 
60
/** Chain node of the list of tables to drop in the background. */
59
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. */
60
64
struct row_mysql_drop_struct{
61
 
        char*                           table_name;
62
 
        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 */
63
68
};
64
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. */
65
75
static UT_LIST_BASE_NODE_T(row_mysql_drop_t)    row_mysql_drop_list;
 
76
/** Flag: has row_mysql_drop_list been initialized? */
66
77
static ibool    row_mysql_drop_list_inited      = FALSE;
67
78
 
68
 
/* Magic table names for invoking various monitor threads */
 
79
/** Magic table names for invoking various monitor threads */
 
80
/* @{ */
69
81
static const char S_innodb_monitor[] = "innodb_monitor";
70
82
static const char S_innodb_lock_monitor[] = "innodb_lock_monitor";
71
83
static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
72
84
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
73
85
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
 
86
/* @} */
74
87
 
75
 
/* Evaluates to true if str1 equals str2_onstack, used for comparing
76
 
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 */
77
94
#define STR_EQ(str1, str1_len, str2_onstack) \
78
95
        ((str1_len) == sizeof(str2_onstack) \
79
96
         && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
80
97
 
81
 
#ifndef UNIV_HOTBACKUP
82
 
/***********************************************************************
83
 
Determine if the given name is a name reserved for MySQL system tables. */
 
98
/*******************************************************************//**
 
99
Determine if the given name is a name reserved for MySQL system tables.
 
100
@return TRUE if name is a MySQL system table name */
84
101
static
85
102
ibool
86
103
row_mysql_is_system_table(
87
104
/*======================*/
88
 
                                 /* out: TRUE if name is a MySQL
89
 
                                 system table name */
90
105
        const char*     name)
91
106
{
92
107
        if (strncmp(name, "mysql/", 6) != 0) {
98
113
               || 0 == strcmp(name + 6, "user")
99
114
               || 0 == strcmp(name + 6, "db"));
100
115
}
101
 
#endif /* !UNIV_HOTBACKUP */
102
116
 
103
 
/*************************************************************************
 
117
/*********************************************************************//**
104
118
If a table is not yet in the drop list, adds the table to the list of tables
105
119
which the master thread drops in background. We need this on Unix because in
106
120
ALTER TABLE MySQL may call drop table even if the table has running queries on
107
121
it. Also, if there are running foreign key checks on the table, we drop the
108
 
table lazily. */
 
122
table lazily.
 
123
@return TRUE if the table was not yet in the drop list, and was added there */
109
124
static
110
125
ibool
111
126
row_add_table_to_background_drop_list(
112
127
/*==================================*/
113
 
                                /* out: TRUE if the table was not yet in the
114
 
                                drop list, and was added there */
115
 
        const char*     name);  /* in: table name */
 
128
        const char*     name);  /*!< in: table name */
116
129
 
117
 
/***********************************************************************
 
130
/*******************************************************************//**
118
131
Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
119
132
static
120
133
void
126
139
        }
127
140
}
128
141
 
129
 
/***********************************************************************
 
142
/*******************************************************************//**
130
143
Frees the blob heap in prebuilt when no longer needed. */
131
144
UNIV_INTERN
132
145
void
133
146
row_mysql_prebuilt_free_blob_heap(
134
147
/*==============================*/
135
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct of a
 
148
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct of a
136
149
                                        ha_innobase:: table handle */
137
150
{
138
151
        mem_heap_free(prebuilt->blob_heap);
139
152
        prebuilt->blob_heap = NULL;
140
153
}
141
154
 
142
 
/***********************************************************************
 
155
/*******************************************************************//**
143
156
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
144
 
format. */
 
157
format.
 
158
@return pointer to the data, we skip the 1 or 2 bytes at the start
 
159
that are used to store the len */
145
160
UNIV_INTERN
146
161
byte*
147
162
row_mysql_store_true_var_len(
148
163
/*=========================*/
149
 
                        /* out: pointer to the data, we skip the 1 or 2 bytes
150
 
                        at the start that are used to store the len */
151
 
        byte*   dest,   /* in: where to store */
152
 
        ulint   len,    /* in: length, must fit in two bytes */
153
 
        ulint   lenlen) /* in: storage length of len: either 1 or 2 bytes */
 
164
        byte*   dest,   /*!< in: where to store */
 
165
        ulint   len,    /*!< in: length, must fit in two bytes */
 
166
        ulint   lenlen) /*!< in: storage length of len: either 1 or 2 bytes */
154
167
{
155
168
        if (lenlen == 2) {
156
169
                ut_a(len < 256 * 256);
168
181
        return(dest + 1);
169
182
}
170
183
 
171
 
/***********************************************************************
 
184
/*******************************************************************//**
172
185
Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
173
 
returns a pointer to the data. */
 
186
returns a pointer to the data.
 
187
@return pointer to the data, we skip the 1 or 2 bytes at the start
 
188
that are used to store the len */
174
189
UNIV_INTERN
175
190
const byte*
176
191
row_mysql_read_true_varchar(
177
192
/*========================*/
178
 
                                /* out: pointer to the data, we skip
179
 
                                the 1 or 2 bytes at the start that are
180
 
                                used to store the len */
181
 
        ulint*          len,    /* out: variable-length field length */
182
 
        const byte*     field,  /* in: field in the MySQL format */
183
 
        ulint           lenlen) /* in: storage length of len: either 1
 
193
        ulint*          len,    /*!< out: variable-length field length */
 
194
        const byte*     field,  /*!< in: field in the MySQL format */
 
195
        ulint           lenlen) /*!< in: storage length of len: either 1
184
196
                                or 2 bytes */
185
197
{
186
198
        if (lenlen == 2) {
196
208
        return(field + 1);
197
209
}
198
210
 
199
 
/***********************************************************************
 
211
/*******************************************************************//**
200
212
Stores a reference to a BLOB in the MySQL format. */
201
213
UNIV_INTERN
202
214
void
203
215
row_mysql_store_blob_ref(
204
216
/*=====================*/
205
 
        byte*           dest,   /* in: where to store */
206
 
        ulint           col_len,/* in: dest buffer size: determines into
 
217
        byte*           dest,   /*!< in: where to store */
 
218
        ulint           col_len,/*!< in: dest buffer size: determines into
207
219
                                how many bytes the BLOB length is stored,
208
220
                                the space for the length may vary from 1
209
221
                                to 4 bytes */
210
 
        const void*     data,   /* in: BLOB data; if the value to store
 
222
        const void*     data,   /*!< in: BLOB data; if the value to store
211
223
                                is SQL NULL this should be NULL pointer */
212
 
        ulint           len)    /* in: BLOB length; if the value to store
 
224
        ulint           len)    /*!< in: BLOB length; if the value to store
213
225
                                is SQL NULL this should be 0; remember
214
226
                                also to set the NULL bit in the MySQL record
215
227
                                header! */
233
245
        memcpy(dest + col_len - 8, &data, sizeof data);
234
246
}
235
247
 
236
 
/***********************************************************************
237
 
Reads a reference to a BLOB in the MySQL format. */
 
248
/*******************************************************************//**
 
249
Reads a reference to a BLOB in the MySQL format.
 
250
@return pointer to BLOB data */
238
251
UNIV_INTERN
239
252
const byte*
240
253
row_mysql_read_blob_ref(
241
254
/*====================*/
242
 
                                        /* out: pointer to BLOB data */
243
 
        ulint*          len,            /* out: BLOB length */
244
 
        const byte*     ref,            /* in: BLOB reference in the
 
255
        ulint*          len,            /*!< out: BLOB length */
 
256
        const byte*     ref,            /*!< in: BLOB reference in the
245
257
                                        MySQL format */
246
 
        ulint           col_len)        /* in: BLOB reference length
 
258
        ulint           col_len)        /*!< in: BLOB reference length
247
259
                                        (not BLOB length) */
248
260
{
249
261
        byte*   data;
255
267
        return(data);
256
268
}
257
269
 
258
 
/******************************************************************
 
270
/**************************************************************//**
259
271
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
260
272
The counterpart of this function is row_sel_field_store_in_mysql_format() in
261
 
row0sel.c. */
 
273
row0sel.c.
 
274
@return up to which byte we used buf in the conversion */
262
275
UNIV_INTERN
263
276
byte*
264
277
row_mysql_store_col_in_innobase_format(
265
278
/*===================================*/
266
 
                                        /* out: up to which byte we used
267
 
                                        buf in the conversion */
268
 
        dfield_t*       dfield,         /* in/out: dfield where dtype
 
279
        dfield_t*       dfield,         /*!< in/out: dfield where dtype
269
280
                                        information must be already set when
270
281
                                        this function is called! */
271
 
        byte*           buf,            /* in/out: buffer for a converted
 
282
        byte*           buf,            /*!< in/out: buffer for a converted
272
283
                                        integer value; this must be at least
273
284
                                        col_len long then! */
274
 
        ibool           row_format_col, /* TRUE if the mysql_data is from
 
285
        ibool           row_format_col, /*!< TRUE if the mysql_data is from
275
286
                                        a MySQL row, FALSE if from a MySQL
276
287
                                        key value;
277
288
                                        in MySQL, a true VARCHAR storage
278
289
                                        format differs in a row and in a
279
290
                                        key value: in a key value the length
280
291
                                        is always stored in 2 bytes! */
281
 
        const byte*     mysql_data,     /* in: MySQL column value, not
 
292
        const byte*     mysql_data,     /*!< in: MySQL column value, not
282
293
                                        SQL NULL; NOTE that dfield may also
283
294
                                        get a pointer to mysql_data,
284
295
                                        therefore do not discard this as long
285
296
                                        as dfield is used! */
286
 
        ulint           col_len,        /* in: MySQL column length; NOTE that
 
297
        ulint           col_len,        /*!< in: MySQL column length; NOTE that
287
298
                                        this is the storage length of the
288
299
                                        column in the MySQL format row, not
289
300
                                        necessarily the length of the actual
290
301
                                        payload data; if the column is a true
291
302
                                        VARCHAR then this is irrelevant */
292
 
        ulint           comp)           /* in: nonzero=compact format */
 
303
        ulint           comp)           /*!< in: nonzero=compact format */
293
304
{
294
305
        const byte*     ptr     = mysql_data;
295
306
        const dtype_t*  dtype;
417
428
        return(buf);
418
429
}
419
430
 
420
 
/******************************************************************
 
431
/**************************************************************//**
421
432
Convert a row in the MySQL format to a row in the Innobase format. Note that
422
433
the function to convert a MySQL format key value to an InnoDB dtuple is
423
434
row_sel_convert_mysql_key_to_innobase() in row0sel.c. */
425
436
void
426
437
row_mysql_convert_row_to_innobase(
427
438
/*==============================*/
428
 
        dtuple_t*       row,            /* in/out: Innobase row where the
 
439
        dtuple_t*       row,            /*!< in/out: Innobase row where the
429
440
                                        field type information is already
430
441
                                        copied there! */
431
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct where template
 
442
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct where template
432
443
                                        must be of type ROW_MYSQL_WHOLE_ROW */
433
 
        byte*           mysql_rec)      /* in: row in the MySQL format;
 
444
        byte*           mysql_rec)      /*!< in: row in the MySQL format;
434
445
                                        NOTE: do not discard as long as
435
446
                                        row is used, as row may contain
436
447
                                        pointers to this record! */
473
484
        }
474
485
}
475
486
 
476
 
/********************************************************************
477
 
Handles user errors and lock waits detected by the database engine. */
 
487
/****************************************************************//**
 
488
Handles user errors and lock waits detected by the database engine.
 
489
@return TRUE if it was a lock wait and we should continue running the
 
490
query thread */
478
491
UNIV_INTERN
479
492
ibool
480
493
row_mysql_handle_errors(
481
494
/*====================*/
482
 
                                /* out: TRUE if it was a lock wait and
483
 
                                we should continue running the query thread */
484
 
        ulint*          new_err,/* out: possible new error encountered in
 
495
        ulint*          new_err,/*!< out: possible new error encountered in
485
496
                                lock wait, or if no new error, the value
486
497
                                of trx->error_state at the entry of this
487
498
                                function */
488
 
        trx_t*          trx,    /* in: transaction */
489
 
        que_thr_t*      thr,    /* in: query thread */
490
 
        trx_savept_t*   savept) /* in: savepoint or NULL */
 
499
        trx_t*          trx,    /*!< in: transaction */
 
500
        que_thr_t*      thr,    /*!< in: query thread */
 
501
        trx_savept_t*   savept) /*!< in: savepoint or NULL */
491
502
{
492
 
#ifndef UNIV_HOTBACKUP
493
503
        ulint   err;
494
504
 
495
505
handle_new_error:
564
574
                      "InnoDB: If the mysqld server crashes"
565
575
                      " after the startup or when\n"
566
576
                      "InnoDB: you dump the tables, look at\n"
567
 
                      "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
568
 
                      "forcing-recovery.html"
 
577
                      "InnoDB: " REFMAN "forcing-recovery.html"
569
578
                      " for help.\n", stderr);
570
579
                break;
571
580
        default:
583
592
        trx->error_state = DB_SUCCESS;
584
593
 
585
594
        return(FALSE);
586
 
#else /* UNIV_HOTBACKUP */
587
 
        /* This function depends on MySQL code that is not included in
588
 
        InnoDB Hot Backup builds.  Besides, this function should never
589
 
        be called in InnoDB Hot Backup. */
590
 
        ut_error;
591
 
        return(FALSE);
592
 
#endif /* UNIV_HOTBACKUP */
593
595
}
594
596
 
595
 
/************************************************************************
596
 
Create a prebuilt struct for a MySQL table handle. */
 
597
/********************************************************************//**
 
598
Create a prebuilt struct for a MySQL table handle.
 
599
@return own: a prebuilt struct */
597
600
UNIV_INTERN
598
601
row_prebuilt_t*
599
602
row_create_prebuilt(
600
603
/*================*/
601
 
                                /* out, own: a prebuilt struct */
602
 
        dict_table_t*   table)  /* in: Innobase table handle */
 
604
        dict_table_t*   table)  /*!< in: Innobase table handle */
603
605
{
604
606
        row_prebuilt_t* prebuilt;
605
607
        mem_heap_t*     heap;
653
655
        return(prebuilt);
654
656
}
655
657
 
656
 
/************************************************************************
 
658
/********************************************************************//**
657
659
Free a prebuilt struct for a MySQL table handle. */
658
660
UNIV_INTERN
659
661
void
660
662
row_prebuilt_free(
661
663
/*==============*/
662
 
        row_prebuilt_t* prebuilt,       /* in, own: prebuilt struct */
663
 
        ibool           dict_locked)    /* in: TRUE=data dictionary locked */
 
664
        row_prebuilt_t* prebuilt,       /*!< in, own: prebuilt struct */
 
665
        ibool           dict_locked)    /*!< in: TRUE=data dictionary locked */
664
666
{
665
667
        ulint   i;
666
668
 
738
740
        mem_heap_free(prebuilt->heap);
739
741
}
740
742
 
741
 
/*************************************************************************
 
743
/*********************************************************************//**
742
744
Updates the transaction pointers in query graphs stored in the prebuilt
743
745
struct. */
744
746
UNIV_INTERN
745
747
void
746
748
row_update_prebuilt_trx(
747
749
/*====================*/
748
 
                                        /* out: prebuilt dtuple */
749
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in MySQL
750
 
                                        handle */
751
 
        trx_t*          trx)            /* in: transaction handle */
 
750
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct
 
751
                                        in MySQL handle */
 
752
        trx_t*          trx)            /*!< in: transaction handle */
752
753
{
753
754
        if (trx->magic_n != TRX_MAGIC_N) {
754
755
                fprintf(stderr,
789
790
        }
790
791
}
791
792
 
792
 
/*************************************************************************
 
793
/*********************************************************************//**
793
794
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
794
795
has not yet been built in the prebuilt struct, then this function first
795
 
builds it. */
 
796
builds it.
 
797
@return prebuilt dtuple; the column type information is also set in it */
796
798
static
797
799
dtuple_t*
798
800
row_get_prebuilt_insert_row(
799
801
/*========================*/
800
 
                                        /* out: prebuilt dtuple; the column
801
 
                                        type information is also set in it */
802
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
802
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
803
803
                                        handle */
804
804
{
805
805
        ins_node_t*     node;
839
839
        return(prebuilt->ins_node->row);
840
840
}
841
841
 
842
 
/*************************************************************************
 
842
/*********************************************************************//**
843
843
Updates the table modification counter and calculates new estimates
844
844
for table and index statistics if necessary. */
845
845
UNIV_INLINE
846
846
void
847
847
row_update_statistics_if_needed(
848
848
/*============================*/
849
 
        dict_table_t*   table)  /* in: table */
 
849
        dict_table_t*   table)  /*!< in: table */
850
850
{
851
851
        ulint   counter;
852
852
 
867
867
        }
868
868
}
869
869
 
870
 
/*************************************************************************
 
870
/*********************************************************************//**
871
871
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
872
872
UNIV_INTERN
873
873
void
874
874
row_unlock_table_autoinc_for_mysql(
875
875
/*===============================*/
876
 
        trx_t*  trx)    /* in/out: transaction */
 
876
        trx_t*  trx)    /*!< in/out: transaction */
877
877
{
878
878
        mutex_enter(&kernel_mutex);
879
879
 
882
882
        mutex_exit(&kernel_mutex);
883
883
}
884
884
 
885
 
/*************************************************************************
 
885
/*********************************************************************//**
886
886
Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
887
887
AUTO_INC lock gives exclusive access to the auto-inc counter of the
888
888
table. The lock is reserved only for the duration of an SQL statement.
889
889
It is not compatible with another AUTO_INC or exclusive lock on the
890
 
table. */
 
890
table.
 
891
@return error code or DB_SUCCESS */
891
892
UNIV_INTERN
892
893
int
893
894
row_lock_table_autoinc_for_mysql(
894
895
/*=============================*/
895
 
                                        /* out: error code or DB_SUCCESS */
896
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in the MySQL
 
896
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in the MySQL
897
897
                                        table handle */
898
898
{
899
899
        trx_t*                  trx     = prebuilt->trx;
962
962
        return((int) err);
963
963
}
964
964
 
965
 
/*************************************************************************
966
 
Sets a table lock on the table mentioned in prebuilt. */
 
965
/*********************************************************************//**
 
966
Sets a table lock on the table mentioned in prebuilt.
 
967
@return error code or DB_SUCCESS */
967
968
UNIV_INTERN
968
969
int
969
970
row_lock_table_for_mysql(
970
971
/*=====================*/
971
 
                                        /* out: error code or DB_SUCCESS */
972
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in the MySQL
 
972
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in the MySQL
973
973
                                        table handle */
974
 
        dict_table_t*   table,          /* in: table to lock, or NULL
 
974
        dict_table_t*   table,          /*!< in: table to lock, or NULL
975
975
                                        if prebuilt->table should be
976
976
                                        locked as
977
977
                                        prebuilt->select_lock_type */
978
 
        ulint           mode)           /* in: lock mode of table
 
978
        ulint           mode)           /*!< in: lock mode of table
979
979
                                        (ignored if table==NULL) */
980
980
{
981
981
        trx_t*          trx             = prebuilt->trx;
1039
1039
        return((int) err);
1040
1040
}
1041
1041
 
1042
 
/*************************************************************************
1043
 
Does an insert for MySQL. */
 
1042
/*********************************************************************//**
 
1043
Does an insert for MySQL.
 
1044
@return error code or DB_SUCCESS */
1044
1045
UNIV_INTERN
1045
1046
int
1046
1047
row_insert_for_mysql(
1047
1048
/*=================*/
1048
 
                                        /* out: error code or DB_SUCCESS */
1049
 
        byte*           mysql_rec,      /* in: row in the MySQL format */
1050
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1049
        byte*           mysql_rec,      /*!< in: row in the MySQL format */
 
1050
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1051
1051
                                        handle */
1052
1052
{
1053
1053
        trx_savept_t    savept;
1071
1071
                        "InnoDB: the MySQL datadir, or have you"
1072
1072
                        " used DISCARD TABLESPACE?\n"
1073
1073
                        "InnoDB: Look from\n"
1074
 
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
1075
 
                        "innodb-troubleshooting.html\n"
 
1074
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
1076
1075
                        "InnoDB: how you can resolve the problem.\n",
1077
1076
                        prebuilt->table->name);
1078
1077
                return(DB_ERROR);
1172
1171
        return((int) err);
1173
1172
}
1174
1173
 
1175
 
/*************************************************************************
 
1174
/*********************************************************************//**
1176
1175
Builds a dummy query graph used in selects. */
1177
1176
UNIV_INTERN
1178
1177
void
1179
1178
row_prebuild_sel_graph(
1180
1179
/*===================*/
1181
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1180
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1182
1181
                                        handle */
1183
1182
{
1184
1183
        sel_node_t*     node;
1198
1197
        }
1199
1198
}
1200
1199
 
1201
 
/*************************************************************************
 
1200
/*********************************************************************//**
1202
1201
Creates an query graph node of 'update' type to be used in the MySQL
1203
 
interface. */
 
1202
interface.
 
1203
@return own: update node */
1204
1204
UNIV_INTERN
1205
1205
upd_node_t*
1206
1206
row_create_update_node_for_mysql(
1207
1207
/*=============================*/
1208
 
                                /* out, own: update node */
1209
 
        dict_table_t*   table,  /* in: table to update */
1210
 
        mem_heap_t*     heap)   /* in: mem heap from which allocated */
 
1208
        dict_table_t*   table,  /*!< in: table to update */
 
1209
        mem_heap_t*     heap)   /*!< in: mem heap from which allocated */
1211
1210
{
1212
1211
        upd_node_t*     node;
1213
1212
 
1234
1233
        return(node);
1235
1234
}
1236
1235
 
1237
 
/*************************************************************************
 
1236
/*********************************************************************//**
1238
1237
Gets pointer to a prebuilt update vector used in updates. If the update
1239
1238
graph has not yet been built in the prebuilt struct, then this function
1240
 
first builds it. */
 
1239
first builds it.
 
1240
@return prebuilt update vector */
1241
1241
UNIV_INTERN
1242
1242
upd_t*
1243
1243
row_get_prebuilt_update_vector(
1244
1244
/*===========================*/
1245
 
                                        /* out: prebuilt update vector */
1246
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1245
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1247
1246
                                        handle */
1248
1247
{
1249
1248
        dict_table_t*   table   = prebuilt->table;
1270
1269
        return(prebuilt->upd_node->update);
1271
1270
}
1272
1271
 
1273
 
/*************************************************************************
1274
 
Does an update or delete of a row for MySQL. */
 
1272
/*********************************************************************//**
 
1273
Does an update or delete of a row for MySQL.
 
1274
@return error code or DB_SUCCESS */
1275
1275
UNIV_INTERN
1276
1276
int
1277
1277
row_update_for_mysql(
1278
1278
/*=================*/
1279
 
                                        /* out: error code or DB_SUCCESS */
1280
 
        byte*           mysql_rec,      /* in: the row to be updated, in
 
1279
        byte*           mysql_rec,      /*!< in: the row to be updated, in
1281
1280
                                        the MySQL format */
1282
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1281
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1283
1282
                                        handle */
1284
1283
{
1285
1284
        trx_savept_t    savept;
1307
1306
                        "InnoDB: the MySQL datadir, or have you"
1308
1307
                        " used DISCARD TABLESPACE?\n"
1309
1308
                        "InnoDB: Look from\n"
1310
 
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
1311
 
                        "innodb-troubleshooting.html\n"
 
1309
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
1312
1310
                        "InnoDB: how you can resolve the problem.\n",
1313
1311
                        prebuilt->table->name);
1314
1312
                return(DB_ERROR);
1426
1424
        return((int) err);
1427
1425
}
1428
1426
 
1429
 
/*************************************************************************
 
1427
/*********************************************************************//**
1430
1428
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
1431
1429
this session is using a READ COMMITTED isolation level. Before
1432
1430
calling this function we must use trx_reset_new_rec_lock_info() and
1436
1434
in the case of an UPDATE or a DELETE statement, where the row lock is of the
1437
1435
LOCK_X type.
1438
1436
Thus, this implements a 'mini-rollback' that releases the latest record
1439
 
locks we set. */
 
1437
locks we set.
 
1438
@return error code or DB_SUCCESS */
1440
1439
UNIV_INTERN
1441
1440
int
1442
1441
row_unlock_for_mysql(
1443
1442
/*=================*/
1444
 
                                        /* out: error code or DB_SUCCESS */
1445
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in MySQL
 
1443
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
1446
1444
                                        handle */
1447
 
        ibool           has_latches_on_recs)/* TRUE if called so that we have
 
1445
        ibool           has_latches_on_recs)/*!< TRUE if called so that we have
1448
1446
                                        the latches on the records under pcur
1449
1447
                                        and clust_pcur, and we do not need to
1450
1448
                                        reposition the cursors. */
1451
1449
{
1452
 
        dict_index_t*   index;
1453
1450
        btr_pcur_t*     pcur            = prebuilt->pcur;
1454
1451
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1455
1452
        trx_t*          trx             = prebuilt->trx;
1456
 
        rec_t*          rec;
1457
 
        mtr_t           mtr;
1458
1453
 
1459
1454
        ut_ad(prebuilt && trx);
1460
1455
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1474
1469
 
1475
1470
        trx->op_info = "unlock_row";
1476
1471
 
1477
 
        index = btr_pcur_get_btr_cur(pcur)->index;
 
1472
        if (prebuilt->new_rec_locks >= 1) {
1478
1473
 
1479
 
        if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
 
1474
                const rec_t*    rec;
 
1475
                dict_index_t*   index;
 
1476
                trx_id_t        rec_trx_id;
 
1477
                mtr_t           mtr;
1480
1478
 
1481
1479
                mtr_start(&mtr);
1482
1480
 
1487
1485
                }
1488
1486
 
1489
1487
                rec = btr_pcur_get_rec(pcur);
1490
 
 
1491
 
                lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1492
 
                                rec, prebuilt->select_lock_type);
1493
 
 
1494
 
                mtr_commit(&mtr);
1495
 
 
1496
 
                /* If the search was done through the clustered index, then
1497
 
                we have not used clust_pcur at all, and we must NOT try to
1498
 
                reset locks on clust_pcur. The values in clust_pcur may be
1499
 
                garbage! */
1500
 
 
1501
 
                if (dict_index_is_clust(index)) {
1502
 
 
1503
 
                        goto func_exit;
1504
 
                }
1505
 
        }
1506
 
 
1507
 
        index = btr_pcur_get_btr_cur(clust_pcur)->index;
1508
 
 
1509
 
        if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
1510
 
 
1511
 
                mtr_start(&mtr);
1512
 
 
1513
 
                /* Restore the cursor position and find the record */
1514
 
 
1515
 
                if (!has_latches_on_recs) {
1516
 
                        btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur,
1517
 
                                                  &mtr);
1518
 
                }
1519
 
 
1520
 
                rec = btr_pcur_get_rec(clust_pcur);
1521
 
 
1522
 
                lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
1523
 
                                rec, prebuilt->select_lock_type);
1524
 
 
1525
 
                mtr_commit(&mtr);
1526
 
        }
1527
 
 
1528
 
func_exit:
 
1488
                index = btr_pcur_get_btr_cur(pcur)->index;
 
1489
 
 
1490
                if (prebuilt->new_rec_locks >= 2) {
 
1491
                        /* Restore the cursor position and find the record
 
1492
                        in the clustered index. */
 
1493
 
 
1494
                        if (!has_latches_on_recs) {
 
1495
                                btr_pcur_restore_position(BTR_SEARCH_LEAF,
 
1496
                                                          clust_pcur, &mtr);
 
1497
                        }
 
1498
 
 
1499
                        rec = btr_pcur_get_rec(clust_pcur);
 
1500
                        index = btr_pcur_get_btr_cur(clust_pcur)->index;
 
1501
                }
 
1502
 
 
1503
                if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
 
1504
                        /* This is not a clustered index record.  We
 
1505
                        do not know how to unlock the record. */
 
1506
                        goto no_unlock;
 
1507
                }
 
1508
 
 
1509
                /* If the record has been modified by this
 
1510
                transaction, do not unlock it. */
 
1511
 
 
1512
                if (index->trx_id_offset) {
 
1513
                        rec_trx_id = trx_read_trx_id(rec
 
1514
                                                     + index->trx_id_offset);
 
1515
                } else {
 
1516
                        mem_heap_t*     heap                    = NULL;
 
1517
                        ulint   offsets_[REC_OFFS_NORMAL_SIZE];
 
1518
                        ulint*  offsets                         = offsets_;
 
1519
 
 
1520
                        rec_offs_init(offsets_);
 
1521
                        offsets = rec_get_offsets(rec, index, offsets,
 
1522
                                                  ULINT_UNDEFINED, &heap);
 
1523
 
 
1524
                        rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
 
1525
 
 
1526
                        if (UNIV_LIKELY_NULL(heap)) {
 
1527
                                mem_heap_free(heap);
 
1528
                        }
 
1529
                }
 
1530
 
 
1531
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
 
1532
                        /* We did not update the record: unlock it */
 
1533
 
 
1534
                        rec = btr_pcur_get_rec(pcur);
 
1535
                        index = btr_pcur_get_btr_cur(pcur)->index;
 
1536
 
 
1537
                        lock_rec_unlock(trx, btr_pcur_get_block(pcur),
 
1538
                                        rec, prebuilt->select_lock_type);
 
1539
 
 
1540
                        if (prebuilt->new_rec_locks >= 2) {
 
1541
                                rec = btr_pcur_get_rec(clust_pcur);
 
1542
                                index = btr_pcur_get_btr_cur(clust_pcur)->index;
 
1543
 
 
1544
                                lock_rec_unlock(trx,
 
1545
                                                btr_pcur_get_block(clust_pcur),
 
1546
                                                rec,
 
1547
                                                prebuilt->select_lock_type);
 
1548
                        }
 
1549
                }
 
1550
no_unlock:
 
1551
                mtr_commit(&mtr);
 
1552
        }
 
1553
 
1529
1554
        trx->op_info = "";
1530
1555
 
1531
1556
        return(DB_SUCCESS);
1532
1557
}
1533
1558
 
1534
 
/**************************************************************************
1535
 
Does a cascaded delete or set null in a foreign key operation. */
 
1559
/**********************************************************************//**
 
1560
Does a cascaded delete or set null in a foreign key operation.
 
1561
@return error code or DB_SUCCESS */
1536
1562
UNIV_INTERN
1537
1563
ulint
1538
1564
row_update_cascade_for_mysql(
1539
1565
/*=========================*/
1540
 
                                /* out: error code or DB_SUCCESS */
1541
 
        que_thr_t*      thr,    /* in: query thread */
1542
 
        upd_node_t*     node,   /* in: update node used in the cascade
 
1566
        que_thr_t*      thr,    /*!< in: query thread */
 
1567
        upd_node_t*     node,   /*!< in: update node used in the cascade
1543
1568
                                or set null operation */
1544
 
        dict_table_t*   table)  /* in: table where we do the operation */
 
1569
        dict_table_t*   table)  /*!< in: table where we do the operation */
1545
1570
{
1546
1571
        ulint   err;
1547
1572
        trx_t*  trx;
1600
1625
        return(err);
1601
1626
}
1602
1627
 
1603
 
/*************************************************************************
 
1628
/*********************************************************************//**
1604
1629
Checks if a table is such that we automatically created a clustered
1605
 
index on it (on row id). */
 
1630
index on it (on row id).
 
1631
@return TRUE if the clustered index was generated automatically */
1606
1632
UNIV_INTERN
1607
1633
ibool
1608
1634
row_table_got_default_clust_index(
1609
1635
/*==============================*/
1610
 
        const dict_table_t*     table)
 
1636
        const dict_table_t*     table)  /*!< in: table */
1611
1637
{
1612
1638
        const dict_index_t*     clust_index;
1613
1639
 
1616
1642
        return(dict_index_get_nth_col(clust_index, 0)->mtype == DATA_SYS);
1617
1643
}
1618
1644
 
1619
 
/*************************************************************************
 
1645
/*********************************************************************//**
1620
1646
Calculates the key number used inside MySQL for an Innobase index. We have
1621
 
to take into account if we generated a default clustered index for the table */
 
1647
to take into account if we generated a default clustered index for the table
 
1648
@return the key number used inside MySQL */
1622
1649
UNIV_INTERN
1623
1650
ulint
1624
1651
row_get_mysql_key_number_for_index(
1625
1652
/*===============================*/
1626
 
        const dict_index_t*     index)
 
1653
        const dict_index_t*     index)  /*!< in: index */
1627
1654
{
1628
1655
        const dict_index_t*     ind;
1629
1656
        ulint                   i;
1646
1673
        return(i);
1647
1674
}
1648
1675
 
1649
 
/*************************************************************************
 
1676
/*********************************************************************//**
1650
1677
Locks the data dictionary in shared mode from modifications, for performing
1651
1678
foreign key check, rollback, or other operation invisible to MySQL. */
1652
1679
UNIV_INTERN
1653
1680
void
1654
1681
row_mysql_freeze_data_dictionary_func(
1655
1682
/*==================================*/
1656
 
        trx_t*          trx,    /* in/out: transaction */
1657
 
        const char*     file,   /* in: file name */
1658
 
        ulint           line)   /* in: line number */
 
1683
        trx_t*          trx,    /*!< in/out: transaction */
 
1684
        const char*     file,   /*!< in: file name */
 
1685
        ulint           line)   /*!< in: line number */
1659
1686
{
1660
1687
        ut_a(trx->dict_operation_lock_mode == 0);
1661
1688
 
1664
1691
        trx->dict_operation_lock_mode = RW_S_LATCH;
1665
1692
}
1666
1693
 
1667
 
/*************************************************************************
 
1694
/*********************************************************************//**
1668
1695
Unlocks the data dictionary shared lock. */
1669
1696
UNIV_INTERN
1670
1697
void
1671
1698
row_mysql_unfreeze_data_dictionary(
1672
1699
/*===============================*/
1673
 
        trx_t*  trx)    /* in/out: transaction */
 
1700
        trx_t*  trx)    /*!< in/out: transaction */
1674
1701
{
1675
1702
        ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
1676
1703
 
1679
1706
        trx->dict_operation_lock_mode = 0;
1680
1707
}
1681
1708
 
1682
 
/*************************************************************************
 
1709
/*********************************************************************//**
1683
1710
Locks the data dictionary exclusively for performing a table create or other
1684
1711
data dictionary modification operation. */
1685
1712
UNIV_INTERN
1686
1713
void
1687
1714
row_mysql_lock_data_dictionary_func(
1688
1715
/*================================*/
1689
 
        trx_t*          trx,    /* in/out: transaction */
1690
 
        const char*     file,   /* in: file name */
1691
 
        ulint           line)   /* in: line number */
 
1716
        trx_t*          trx,    /*!< in/out: transaction */
 
1717
        const char*     file,   /*!< in: file name */
 
1718
        ulint           line)   /*!< in: line number */
1692
1719
{
1693
1720
        ut_a(trx->dict_operation_lock_mode == 0
1694
1721
             || trx->dict_operation_lock_mode == RW_X_LATCH);
1702
1729
        mutex_enter(&(dict_sys->mutex));
1703
1730
}
1704
1731
 
1705
 
/*************************************************************************
 
1732
/*********************************************************************//**
1706
1733
Unlocks the data dictionary exclusive lock. */
1707
1734
UNIV_INTERN
1708
1735
void
1709
1736
row_mysql_unlock_data_dictionary(
1710
1737
/*=============================*/
1711
 
        trx_t*  trx)    /* in/out: transaction */
 
1738
        trx_t*  trx)    /*!< in/out: transaction */
1712
1739
{
1713
1740
        ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
1714
1741
 
1721
1748
        trx->dict_operation_lock_mode = 0;
1722
1749
}
1723
1750
 
1724
 
#ifndef UNIV_HOTBACKUP
1725
 
/*************************************************************************
 
1751
/*********************************************************************//**
1726
1752
Creates a table for MySQL. If the name of the table ends in
1727
1753
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
1728
1754
"innodb_table_monitor", then this will also start the printing of monitor
1729
1755
output by the master thread. If the table name ends in "innodb_mem_validate",
1730
 
InnoDB will try to invoke mem_validate(). */
 
1756
InnoDB will try to invoke mem_validate().
 
1757
@return error code or DB_SUCCESS */
1731
1758
UNIV_INTERN
1732
1759
int
1733
1760
row_create_table_for_mysql(
1734
1761
/*=======================*/
1735
 
                                /* out: error code or DB_SUCCESS */
1736
 
        dict_table_t*   table,  /* in, own: table definition
 
1762
        dict_table_t*   table,  /*!< in, own: table definition
1737
1763
                                (will be freed) */
1738
 
        trx_t*          trx)    /* in: transaction handle */
 
1764
        trx_t*          trx)    /*!< in: transaction handle */
1739
1765
{
1740
1766
        tab_node_t*     node;
1741
1767
        mem_heap_t*     heap;
1902
1928
                      " and DROP TABLE will\n"
1903
1929
                      "InnoDB: succeed.\n"
1904
1930
                      "InnoDB: You can look for further help from\n"
1905
 
                      "InnoDB: "
1906
 
                      "http://dev.mysql.com/doc/refman/5.1/en/"
1907
 
                      "innodb-troubleshooting.html\n", stderr);
 
1931
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
 
1932
                      stderr);
1908
1933
 
1909
1934
                /* We may also get err == DB_ERROR if the .ibd file for the
1910
1935
                table already exists */
1919
1944
        return((int) err);
1920
1945
}
1921
1946
 
1922
 
/*************************************************************************
 
1947
/*********************************************************************//**
1923
1948
Does an index creation operation for MySQL. TODO: currently failure
1924
1949
to create an index results in dropping the whole table! This is no problem
1925
 
currently as all indexes must be created at the same time as the table. */
 
1950
currently as all indexes must be created at the same time as the table.
 
1951
@return error number or DB_SUCCESS */
1926
1952
UNIV_INTERN
1927
1953
int
1928
1954
row_create_index_for_mysql(
1929
1955
/*=======================*/
1930
 
                                        /* out: error number or DB_SUCCESS */
1931
 
        dict_index_t*   index,          /* in, own: index definition
 
1956
        dict_index_t*   index,          /*!< in, own: index definition
1932
1957
                                        (will be freed) */
1933
 
        trx_t*          trx,            /* in: transaction handle */
1934
 
        const ulint*    field_lengths)  /* in: if not NULL, must contain
 
1958
        trx_t*          trx,            /*!< in: transaction handle */
 
1959
        const ulint*    field_lengths)  /*!< in: if not NULL, must contain
1935
1960
                                        dict_index_get_n_fields(index)
1936
1961
                                        actual field lengths for the
1937
1962
                                        index columns, which are
2046
2071
        return((int) err);
2047
2072
}
2048
2073
 
2049
 
/*************************************************************************
 
2074
/*********************************************************************//**
2050
2075
Scans a table create SQL string and adds to the data dictionary
2051
2076
the foreign key constraints declared in the string. This function
2052
2077
should be called after the indexes for a table have been created.
2053
2078
Each foreign key constraint must be accompanied with indexes in
2054
2079
bot participating tables. The indexes are allowed to contain more
2055
2080
fields than mentioned in the constraint. Check also that foreign key
2056
 
constraints which reference this table are ok. */
 
2081
constraints which reference this table are ok.
 
2082
@return error code or DB_SUCCESS */
2057
2083
UNIV_INTERN
2058
2084
int
2059
2085
row_table_add_foreign_constraints(
2060
2086
/*==============================*/
2061
 
                                        /* out: error code or DB_SUCCESS */
2062
 
        trx_t*          trx,            /* in: transaction */
2063
 
        const char*     sql_string,     /* in: table create statement where
 
2087
        trx_t*          trx,            /*!< in: transaction */
 
2088
        const char*     sql_string,     /*!< in: table create statement where
2064
2089
                                        foreign keys are declared like:
2065
2090
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2066
2091
                                        table2 can be written also with the
2067
2092
                                        database name before it: test.table2 */
2068
 
        const char*     name,           /* in: table full name in the
 
2093
        const char*     name,           /*!< in: table full name in the
2069
2094
                                        normalized form
2070
2095
                                        database_name/table_name */
2071
 
        ibool           reject_fks)     /* in: if TRUE, fail with error
 
2096
        ibool           reject_fks)     /*!< in: if TRUE, fail with error
2072
2097
                                        code DB_CANNOT_ADD_CONSTRAINT if
2073
2098
                                        any foreign keys are found. */
2074
2099
{
2088
2113
 
2089
2114
        err = dict_create_foreign_constraints(trx, sql_string, name,
2090
2115
                                              reject_fks);
2091
 
#ifndef UNIV_HOTBACKUP
2092
2116
        if (err == DB_SUCCESS) {
2093
2117
                /* Check that also referencing constraints are ok */
2094
2118
                err = dict_load_foreigns(name, TRUE);
2095
2119
        }
2096
 
#endif /* !UNIV_HOTBACKUP */
 
2120
 
2097
2121
        if (err != DB_SUCCESS) {
2098
2122
                /* We have special error handling here */
2099
2123
 
2111
2135
        return((int) err);
2112
2136
}
2113
2137
 
2114
 
/*************************************************************************
 
2138
/*********************************************************************//**
2115
2139
Drops a table for MySQL as a background operation. MySQL relies on Unix
2116
2140
in ALTER TABLE to the fact that the table handler does not remove the
2117
2141
table before all handles to it has been removed. Furhermore, the MySQL's
2118
2142
call to drop table must be non-blocking. Therefore we do the drop table
2119
2143
as a background operation, which is taken care of by the master thread
2120
 
in srv0srv.c. */
 
2144
in srv0srv.c.
 
2145
@return error code or DB_SUCCESS */
2121
2146
static
2122
2147
int
2123
2148
row_drop_table_for_mysql_in_background(
2124
2149
/*===================================*/
2125
 
                                /* out: error code or DB_SUCCESS */
2126
 
        const char*     name)   /* in: table name */
 
2150
        const char*     name)   /*!< in: table name */
2127
2151
{
2128
2152
        ulint   error;
2129
2153
        trx_t*  trx;
2157
2181
        return((int) error);
2158
2182
}
2159
2183
 
2160
 
/*************************************************************************
 
2184
/*********************************************************************//**
2161
2185
The master thread in srv0srv.c calls this regularly to drop tables which
2162
2186
we must drop in background after queries to them have ended. Such lazy
2163
 
dropping of tables is needed in ALTER TABLE on Unix. */
 
2187
dropping of tables is needed in ALTER TABLE on Unix.
 
2188
@return how many tables dropped + remaining tables in list */
2164
2189
UNIV_INTERN
2165
2190
ulint
2166
2191
row_drop_tables_for_mysql_in_background(void)
2167
2192
/*=========================================*/
2168
 
                                        /* out: how many tables dropped
2169
 
                                        + remaining tables in list */
2170
2193
{
2171
2194
        row_mysql_drop_t*       drop;
2172
2195
        dict_table_t*           table;
2233
2256
        goto loop;
2234
2257
}
2235
2258
 
2236
 
/*************************************************************************
 
2259
/*********************************************************************//**
2237
2260
Get the background drop list length. NOTE: the caller must own the kernel
2238
 
mutex! */
 
2261
mutex!
 
2262
@return how many tables in list */
2239
2263
UNIV_INTERN
2240
2264
ulint
2241
2265
row_get_background_drop_list_len_low(void)
2242
2266
/*======================================*/
2243
 
                                        /* out: how many tables in list */
2244
2267
{
2245
2268
        ut_ad(mutex_own(&kernel_mutex));
2246
2269
 
2253
2276
        return(UT_LIST_GET_LEN(row_mysql_drop_list));
2254
2277
}
2255
2278
 
2256
 
/*************************************************************************
 
2279
/*********************************************************************//**
2257
2280
If a table is not yet in the drop list, adds the table to the list of tables
2258
2281
which the master thread drops in background. We need this on Unix because in
2259
2282
ALTER TABLE MySQL may call drop table even if the table has running queries on
2260
2283
it. Also, if there are running foreign key checks on the table, we drop the
2261
 
table lazily. */
 
2284
table lazily.
 
2285
@return TRUE if the table was not yet in the drop list, and was added there */
2262
2286
static
2263
2287
ibool
2264
2288
row_add_table_to_background_drop_list(
2265
2289
/*==================================*/
2266
 
                                /* out: TRUE if the table was not yet in the
2267
 
                                drop list, and was added there */
2268
 
        const char*     name)   /* in: table name */
 
2290
        const char*     name)   /*!< in: table name */
2269
2291
{
2270
2292
        row_mysql_drop_t*       drop;
2271
2293
 
2307
2329
        return(TRUE);
2308
2330
}
2309
2331
 
2310
 
/*************************************************************************
 
2332
/*********************************************************************//**
2311
2333
Discards the tablespace of a table which stored in an .ibd file. Discarding
2312
2334
means that this function deletes the .ibd file and assigns a new table id for
2313
 
the table. Also the flag table->ibd_file_missing is set TRUE. */
 
2335
the table. Also the flag table->ibd_file_missing is set TRUE.
 
2336
@return error code or DB_SUCCESS */
2314
2337
UNIV_INTERN
2315
2338
int
2316
2339
row_discard_tablespace_for_mysql(
2317
2340
/*=============================*/
2318
 
                                /* out: error code or DB_SUCCESS */
2319
 
        const char*     name,   /* in: table name */
2320
 
        trx_t*          trx)    /* in: transaction handle */
 
2341
        const char*     name,   /*!< in: table name */
 
2342
        trx_t*          trx)    /*!< in: transaction handle */
2321
2343
{
2322
2344
        dict_foreign_t* foreign;
2323
2345
        dulint          new_id;
2499
2521
        return((int) err);
2500
2522
}
2501
2523
 
2502
 
/*********************************************************************
 
2524
/*****************************************************************//**
2503
2525
Imports a tablespace. The space id in the .ibd file must match the space id
2504
 
of the table in the data dictionary. */
 
2526
of the table in the data dictionary.
 
2527
@return error code or DB_SUCCESS */
2505
2528
UNIV_INTERN
2506
2529
int
2507
2530
row_import_tablespace_for_mysql(
2508
2531
/*============================*/
2509
 
                                /* out: error code or DB_SUCCESS */
2510
 
        const char*     name,   /* in: table name */
2511
 
        trx_t*          trx)    /* in: transaction handle */
 
2532
        const char*     name,   /*!< in: table name */
 
2533
        trx_t*          trx)    /*!< in: transaction handle */
2512
2534
{
2513
2535
        dict_table_t*   table;
2514
2536
        ibool           success;
2637
2659
        return((int) err);
2638
2660
}
2639
2661
 
2640
 
/*************************************************************************
2641
 
Truncates a table for MySQL. */
 
2662
/*********************************************************************//**
 
2663
Truncates a table for MySQL.
 
2664
@return error code or DB_SUCCESS */
2642
2665
UNIV_INTERN
2643
2666
int
2644
2667
row_truncate_table_for_mysql(
2645
2668
/*=========================*/
2646
 
                                /* out: error code or DB_SUCCESS */
2647
 
        dict_table_t*   table,  /* in: table handle */
2648
 
        trx_t*          trx)    /* in: transaction handle */
 
2669
        dict_table_t*   table,  /*!< in: table handle */
 
2670
        trx_t*          trx)    /*!< in: transaction handle */
2649
2671
{
2650
2672
        dict_foreign_t* foreign;
2651
2673
        ulint           err;
2943
2965
                dict_table_change_id_in_cache(table, new_id);
2944
2966
        }
2945
2967
 
2946
 
        /* MySQL calls ha_innobase::reset_auto_increment() which does
2947
 
        the same thing. */
 
2968
        /* 
 
2969
          MySQL calls ha_innobase::reset_auto_increment() which does
 
2970
          the same thing. 
 
2971
        */
2948
2972
        dict_table_autoinc_lock(table);
2949
2973
        dict_table_autoinc_initialize(table, 1);
2950
2974
        dict_table_autoinc_unlock(table);
2963
2987
        return((int) err);
2964
2988
}
2965
2989
 
2966
 
/*************************************************************************
 
2990
/*********************************************************************//**
2967
2991
Drops a table for MySQL.  If the name of the dropped table ends in
2968
2992
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
2969
2993
"innodb_table_monitor", then this will also stop the printing of monitor
2970
2994
output by the master thread.  If the data dictionary was not already locked
2971
2995
by the transaction, the transaction will be committed.  Otherwise, the
2972
 
data dictionary will remain locked. */
 
2996
data dictionary will remain locked.
 
2997
@return error code or DB_SUCCESS */
2973
2998
UNIV_INTERN
2974
2999
int
2975
3000
row_drop_table_for_mysql(
2976
3001
/*=====================*/
2977
 
                                /* out: error code or DB_SUCCESS */
2978
 
        const char*     name,   /* in: table name */
2979
 
        trx_t*          trx,    /* in: transaction handle */
2980
 
        ibool           drop_db)/* in: TRUE=dropping whole database */
 
3002
        const char*     name,   /*!< in: table name */
 
3003
        trx_t*          trx,    /*!< in: transaction handle */
 
3004
        ibool           drop_db)/*!< in: TRUE=dropping whole database */
2981
3005
{
2982
3006
        dict_foreign_t* foreign;
2983
3007
        dict_table_t*   table;
3059
3083
        table = dict_table_get_low(name);
3060
3084
 
3061
3085
        if (!table) {
 
3086
#if defined(BUILD_DRIZZLE)
3062
3087
                err = ENOENT;
 
3088
#else
 
3089
                err = DB_TABLE_NOT_FOUND;
 
3090
                ut_print_timestamp(stderr);
 
3091
 
 
3092
                fputs("  InnoDB: Error: table ", stderr);
 
3093
                ut_print_name(stderr, trx, TRUE, name);
 
3094
                fputs(" does not exist in the InnoDB internal\n"
 
3095
                      "InnoDB: data dictionary though MySQL is"
 
3096
                      " trying to drop it.\n"
 
3097
                      "InnoDB: Have you copied the .frm file"
 
3098
                      " of the table to the\n"
 
3099
                      "InnoDB: MySQL database directory"
 
3100
                      " from another database?\n"
 
3101
                      "InnoDB: You can look for further help from\n"
 
3102
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
 
3103
                      stderr);
 
3104
#endif /* BUILD_DRIZZLE */
3063
3105
                goto funct_exit;
3064
3106
        }
3065
3107
 
3338
3380
 
3339
3381
        trx->op_info = "";
3340
3382
 
3341
 
#ifndef UNIV_HOTBACKUP
3342
3383
        srv_wake_master_thread();
3343
 
#endif /* !UNIV_HOTBACKUP */
3344
3384
 
3345
3385
        return((int) err);
3346
3386
}
3347
3387
 
3348
 
/***********************************************************************
 
3388
/*******************************************************************//**
3349
3389
Drop all foreign keys in a database, see Bug#18942.
3350
 
Called at the end of row_drop_database_for_mysql(). */
 
3390
Called at the end of row_drop_database_for_mysql().
 
3391
@return error code or DB_SUCCESS */
3351
3392
static
3352
3393
ulint
3353
3394
drop_all_foreign_keys_in_db(
3354
3395
/*========================*/
3355
 
                                /* out: error code or DB_SUCCESS */
3356
 
        const char*     name,   /* in: database name which ends to '/' */
3357
 
        trx_t*          trx)    /* in: transaction handle */
 
3396
        const char*     name,   /*!< in: database name which ends to '/' */
 
3397
        trx_t*          trx)    /*!< in: transaction handle */
3358
3398
{
3359
3399
        pars_info_t*    pinfo;
3360
3400
        ulint           err;
3365
3405
 
3366
3406
        pars_info_add_str_literal(pinfo, "dbname", name);
3367
3407
 
3368
 
/* true if for_name is not prefixed with dbname */
 
3408
/** true if for_name is not prefixed with dbname */
3369
3409
#define TABLE_NOT_IN_THIS_DB \
3370
3410
"SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
3371
3411
 
3405
3445
        return(err);
3406
3446
}
3407
3447
 
3408
 
/*************************************************************************
3409
 
Drops a database for MySQL. */
 
3448
/*********************************************************************//**
 
3449
Drops a database for MySQL.
 
3450
@return error code or DB_SUCCESS */
3410
3451
UNIV_INTERN
3411
3452
int
3412
3453
row_drop_database_for_mysql(
3413
3454
/*========================*/
3414
 
                                /* out: error code or DB_SUCCESS */
3415
 
        const char*     name,   /* in: database name which ends to '/' */
3416
 
        trx_t*          trx)    /* in: transaction handle */
 
3455
        const char*     name,   /*!< in: database name which ends to '/' */
 
3456
        trx_t*          trx)    /*!< in: transaction handle */
3417
3457
{
3418
3458
        dict_table_t* table;
3419
3459
        char*   table_name;
3499
3539
        return(err);
3500
3540
}
3501
3541
 
3502
 
/*************************************************************************
 
3542
/*********************************************************************//**
3503
3543
Checks if a table name contains the string "/#sql" which denotes temporary
3504
 
tables in MySQL. */
 
3544
tables in MySQL.
 
3545
@return TRUE if temporary table */
3505
3546
static
3506
3547
ibool
3507
3548
row_is_mysql_tmp_table_name(
3508
3549
/*========================*/
3509
 
                                /* out: TRUE if temporary table */
3510
 
        const char*     name)   /* in: table name in the form
 
3550
        const char*     name)   /*!< in: table name in the form
3511
3551
                                'database/tablename' */
3512
3552
{
3513
3553
        return(strstr(name, "/#sql") != NULL);
3514
3554
        /* return(strstr(name, "/@0023sql") != NULL); */
3515
3555
}
3516
3556
 
3517
 
/********************************************************************
3518
 
Delete a single constraint. */
 
3557
/****************************************************************//**
 
3558
Delete a single constraint.
 
3559
@return error code or DB_SUCCESS */
3519
3560
static
3520
3561
int
3521
3562
row_delete_constraint_low(
3522
3563
/*======================*/
3523
 
                                        /* out: error code or DB_SUCCESS */
3524
 
        const char*     id,             /* in: constraint id */
3525
 
        trx_t*          trx)            /* in: transaction handle */
 
3564
        const char*     id,             /*!< in: constraint id */
 
3565
        trx_t*          trx)            /*!< in: transaction handle */
3526
3566
{
3527
3567
        pars_info_t*    info = pars_info_create();
3528
3568
 
3537
3577
                            , FALSE, trx));
3538
3578
}
3539
3579
 
3540
 
/********************************************************************
3541
 
Delete a single constraint. */
 
3580
/****************************************************************//**
 
3581
Delete a single constraint.
 
3582
@return error code or DB_SUCCESS */
3542
3583
static
3543
3584
int
3544
3585
row_delete_constraint(
3545
3586
/*==================*/
3546
 
                                        /* out: error code or DB_SUCCESS */
3547
 
        const char*     id,             /* in: constraint id */
3548
 
        const char*     database_name,  /* in: database name, with the
 
3587
        const char*     id,             /*!< in: constraint id */
 
3588
        const char*     database_name,  /*!< in: database name, with the
3549
3589
                                        trailing '/' */
3550
 
        mem_heap_t*     heap,           /* in: memory heap */
3551
 
        trx_t*          trx)            /* in: transaction handle */
 
3590
        mem_heap_t*     heap,           /*!< in: memory heap */
 
3591
        trx_t*          trx)            /*!< in: transaction handle */
3552
3592
{
3553
3593
        ulint           err;
3554
3594
 
3570
3610
        return((int) err);
3571
3611
}
3572
3612
 
3573
 
/*************************************************************************
3574
 
Renames a table for MySQL. */
 
3613
/*********************************************************************//**
 
3614
Renames a table for MySQL.
 
3615
@return error code or DB_SUCCESS */
3575
3616
UNIV_INTERN
3576
3617
ulint
3577
3618
row_rename_table_for_mysql(
3578
3619
/*=======================*/
3579
 
                                        /* out: error code or DB_SUCCESS */
3580
 
        const char*     old_name,       /* in: old table name */
3581
 
        const char*     new_name,       /* in: new table name */
3582
 
        trx_t*          trx,            /* in: transaction handle */
3583
 
        ibool           commit)         /* in: if TRUE then commit trx */
 
3620
        const char*     old_name,       /*!< in: old table name */
 
3621
        const char*     new_name,       /*!< in: new table name */
 
3622
        trx_t*          trx,            /*!< in: transaction handle */
 
3623
        ibool           commit)         /*!< in: if TRUE then commit trx */
3584
3624
{
3585
3625
        dict_table_t*   table;
3586
3626
        ulint           err                     = DB_ERROR;
3625
3665
        table = dict_table_get_low(old_name);
3626
3666
 
3627
3667
        if (!table) {
3628
 
                err= ENOENT;
 
3668
#if defined(BUILD_DRIZZLE)
 
3669
                err = ENOENT;
 
3670
#else
 
3671
                err = DB_TABLE_NOT_FOUND;
 
3672
                ut_print_timestamp(stderr);
 
3673
 
 
3674
                fputs("  InnoDB: Error: table ", stderr);
 
3675
                ut_print_name(stderr, trx, TRUE, old_name);
 
3676
                fputs(" does not exist in the InnoDB internal\n"
 
3677
                      "InnoDB: data dictionary though MySQL is"
 
3678
                      " trying to rename the table.\n"
 
3679
                      "InnoDB: Have you copied the .frm file"
 
3680
                      " of the table to the\n"
 
3681
                      "InnoDB: MySQL database directory"
 
3682
                      " from another database?\n"
 
3683
                      "InnoDB: You can look for further help from\n"
 
3684
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
 
3685
                      stderr);
 
3686
#endif /* BUILD_DRIZZLE */
3629
3687
                goto funct_exit;
3630
3688
        } else if (table->ibd_file_missing) {
3631
3689
                err = DB_TABLE_NOT_FOUND;
3636
3694
                fputs(" does not have an .ibd file"
3637
3695
                      " in the database directory.\n"
3638
3696
                      "InnoDB: You can look for further help from\n"
3639
 
                      "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3640
 
                      "innodb-troubleshooting.html\n",
 
3697
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
3641
3698
                      stderr);
3642
3699
                goto funct_exit;
3643
3700
        } else if (new_is_tmp) {
3789
3846
                              "InnoDB: Have you deleted the .frm file"
3790
3847
                              " and not used DROP TABLE?\n"
3791
3848
                              "InnoDB: You can look for further help from\n"
3792
 
                              "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3793
 
                              "innodb-troubleshooting.html\n"
 
3849
                              "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
3794
3850
                              "InnoDB: If table ", stderr);
3795
3851
                        ut_print_name(stderr, trx, TRUE, new_name);
3796
3852
                        fputs(" is a temporary table #sql..., then"
3879
3935
        return(err);
3880
3936
}
3881
3937
 
3882
 
/*************************************************************************
 
3938
/*********************************************************************//**
3883
3939
Checks that the index contains entries in an ascending order, unique
3884
3940
constraint is not broken, and calculates the number of index entries
3885
 
in the read view of the current transaction. */
 
3941
in the read view of the current transaction.
 
3942
@return TRUE if ok */
3886
3943
static
3887
3944
ibool
3888
3945
row_scan_and_check_index(
3889
3946
/*=====================*/
3890
 
                                        /* out: TRUE if ok */
3891
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in MySQL */
3892
 
        dict_index_t*   index,          /* in: index */
3893
 
        ulint*          n_rows)         /* out: number of entries seen in the
 
3947
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL */
 
3948
        dict_index_t*   index,          /*!< in: index */
 
3949
        ulint*          n_rows)         /*!< out: number of entries seen in the
3894
3950
                                        current consistent read */
3895
3951
{
3896
3952
        dtuple_t*       prev_entry      = NULL;
3912
3968
 
3913
3969
        *n_rows = 0;
3914
3970
 
 
3971
        if (!row_merge_is_index_usable(prebuilt->trx, index)) {
 
3972
                /* A newly created index may lack some delete-marked
 
3973
                records that may exist in the read view of
 
3974
                prebuilt->trx.  Thus, such indexes must not be
 
3975
                accessed by consistent read. */
 
3976
                return(is_ok);
 
3977
        }
 
3978
 
3915
3979
        buf = mem_alloc(UNIV_PAGE_SIZE);
3916
3980
        heap = mem_heap_create(100);
3917
3981
 
3919
3983
        in scanning the index entries */
3920
3984
 
3921
3985
        prebuilt->index = index;
 
3986
        /* row_merge_is_index_usable() was already checked above. */
 
3987
        prebuilt->index_usable = TRUE;
3922
3988
        prebuilt->sql_stat_start = TRUE;
3923
3989
        prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
3924
3990
        prebuilt->n_template = 0;
3938
4004
                }
3939
4005
                cnt = 1000;
3940
4006
        }
3941
 
        if (ret != DB_SUCCESS) {
 
4007
 
 
4008
        switch (ret) {
 
4009
        case DB_SUCCESS:
 
4010
                break;
 
4011
        default:
 
4012
                ut_print_timestamp(stderr);
 
4013
                fputs("  InnoDB: Warning: CHECK TABLE on ", stderr);
 
4014
                dict_index_name_print(stderr, prebuilt->trx, index);
 
4015
                fprintf(stderr, " returned %lu\n", ret);
 
4016
                /* fall through (this error is ignored by CHECK TABLE) */
 
4017
        case DB_END_OF_INDEX:
3942
4018
func_exit:
3943
4019
                mem_free(buf);
3944
4020
                mem_heap_free(heap);
4034
4110
        goto loop;
4035
4111
}
4036
4112
 
4037
 
/*************************************************************************
4038
 
Checks a table for corruption. */
 
4113
/*********************************************************************//**
 
4114
Checks a table for corruption.
 
4115
@return DB_ERROR or DB_SUCCESS */
4039
4116
UNIV_INTERN
4040
4117
ulint
4041
4118
row_check_table_for_mysql(
4042
4119
/*======================*/
4043
 
                                        /* out: DB_ERROR or DB_SUCCESS */
4044
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
4120
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
4045
4121
                                        handle */
4046
4122
{
4047
4123
        dict_table_t*   table           = prebuilt->table;
4062
4138
                        "InnoDB: the MySQL datadir, or have you"
4063
4139
                        " used DISCARD TABLESPACE?\n"
4064
4140
                        "InnoDB: Look from\n"
4065
 
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
4066
 
                        "innodb-troubleshooting.html\n"
 
4141
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
4067
4142
                        "InnoDB: how you can resolve the problem.\n",
4068
4143
                        table->name);
4069
4144
                return(DB_ERROR);
4146
4221
 
4147
4222
        return(ret);
4148
4223
}
4149
 
#endif /* !UNIV_HOTBACKUP */
4150
4224
 
4151
 
/*************************************************************************
4152
 
Determines if a table is a magic monitor table. */
 
4225
/*********************************************************************//**
 
4226
Determines if a table is a magic monitor table.
 
4227
@return TRUE if monitor table */
4153
4228
UNIV_INTERN
4154
4229
ibool
4155
4230
row_is_magic_monitor_table(
4156
4231
/*=======================*/
4157
 
                                        /* out: TRUE if monitor table */
4158
 
        const char*     table_name)     /* in: name of the table, in the
 
4232
        const char*     table_name)     /*!< in: name of the table, in the
4159
4233
                                        form database/table_name */
4160
4234
{
4161
4235
        const char*     name; /* table_name without database/ */