mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge sinisa@bk-internal.mysql.com:/home/bk/mysql-4.0
into sinisa.nasamreza.org:/mnt/work/mysql-4.0
This commit is contained in:
@@ -19,6 +19,11 @@
|
|||||||
#ifndef _global_h
|
#ifndef _global_h
|
||||||
#define _global_h
|
#define _global_h
|
||||||
|
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
#define HAVE_REPLICATION
|
||||||
|
#define HAVE_EXTERNAL_CLIENT
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined( __EMX__) && !defined( MYSQL_SERVER)
|
#if defined( __EMX__) && !defined( MYSQL_SERVER)
|
||||||
/* moved here to use below VOID macro redefinition */
|
/* moved here to use below VOID macro redefinition */
|
||||||
#define INCL_BASE
|
#define INCL_BASE
|
||||||
|
@@ -106,7 +106,7 @@ buf_flush_ready_for_replace(
|
|||||||
BUF_BLOCK_FILE_PAGE and in the LRU list*/
|
BUF_BLOCK_FILE_PAGE and in the LRU list*/
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||||
|
|
||||||
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
|
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
|
||||||
|| (block->buf_fix_count != 0)
|
|| (block->buf_fix_count != 0)
|
||||||
@@ -227,7 +227,9 @@ buf_flush_buffered_writes(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < trx_doublewrite->first_free; i++) {
|
for (i = 0; i < trx_doublewrite->first_free; i++) {
|
||||||
|
|
||||||
block = trx_doublewrite->buf_block_arr[i];
|
block = trx_doublewrite->buf_block_arr[i];
|
||||||
|
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||||
|
|
||||||
if (block->check_index_page_at_flush
|
if (block->check_index_page_at_flush
|
||||||
&& !page_simple_validate(block->frame)) {
|
&& !page_simple_validate(block->frame)) {
|
||||||
@@ -236,10 +238,12 @@ buf_flush_buffered_writes(void)
|
|||||||
|
|
||||||
ut_print_timestamp(stderr);
|
ut_print_timestamp(stderr);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
" InnoDB: Apparent corruption of an index page\n"
|
" InnoDB: Apparent corruption of an index page n:o %lu in space %lu\n"
|
||||||
"InnoDB: to be written to data file. We intentionally crash server\n"
|
"InnoDB: to be written to data file. We intentionally crash server\n"
|
||||||
"InnoDB: to prevent corrupt data from ending up in data\n"
|
"InnoDB: to prevent corrupt data from ending up in data\n"
|
||||||
"InnoDB: files.\n");
|
"InnoDB: files.\n",
|
||||||
|
block->offset, block->space);
|
||||||
|
|
||||||
ut_a(0);
|
ut_a(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,6 +436,8 @@ buf_flush_try_page(
|
|||||||
|
|
||||||
block = buf_page_hash_get(space, offset);
|
block = buf_page_hash_get(space, offset);
|
||||||
|
|
||||||
|
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||||
|
|
||||||
if (flush_type == BUF_FLUSH_LIST
|
if (flush_type == BUF_FLUSH_LIST
|
||||||
&& block && buf_flush_ready_for_flush(block, flush_type)) {
|
&& block && buf_flush_ready_for_flush(block, flush_type)) {
|
||||||
|
|
||||||
|
@@ -1173,6 +1173,7 @@ dict_create_add_foreigns_to_dictionary(
|
|||||||
if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) {
|
if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
|
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
|
||||||
|
|
||||||
return(DB_ERROR);
|
return(DB_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1259,6 +1260,13 @@ loop:
|
|||||||
"InnoDB: at http://www.innodb.com/ibman.html\n");
|
"InnoDB: at http://www.innodb.com/ibman.html\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Internal error in foreign key constraint creation for table %.500s.\n"
|
||||||
|
"See the MySQL .err log in the datadir for more information.\n", table->name);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -185,6 +185,12 @@ dict_foreign_free(
|
|||||||
/*==============*/
|
/*==============*/
|
||||||
dict_foreign_t* foreign); /* in, own: foreign key struct */
|
dict_foreign_t* foreign); /* in, own: foreign key struct */
|
||||||
|
|
||||||
|
/* Buffer for storing detailed information about the latest foreig key
|
||||||
|
error */
|
||||||
|
char* dict_foreign_err_buf = NULL;
|
||||||
|
mutex_t dict_foreign_err_mutex; /* mutex protecting the buffer */
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
Checks if the database name in two table names is the same. */
|
Checks if the database name in two table names is the same. */
|
||||||
static
|
static
|
||||||
@@ -573,6 +579,11 @@ dict_init(void)
|
|||||||
|
|
||||||
rw_lock_create(&dict_operation_lock);
|
rw_lock_create(&dict_operation_lock);
|
||||||
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
|
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
|
||||||
|
|
||||||
|
dict_foreign_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
dict_foreign_err_buf[0] = '\0';
|
||||||
|
mutex_create(&dict_foreign_err_mutex);
|
||||||
|
mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -1818,6 +1829,7 @@ dict_foreign_add_to_cache(
|
|||||||
dict_foreign_t* for_in_cache = NULL;
|
dict_foreign_t* for_in_cache = NULL;
|
||||||
dict_index_t* index;
|
dict_index_t* index;
|
||||||
ibool added_to_referenced_list = FALSE;
|
ibool added_to_referenced_list = FALSE;
|
||||||
|
char* buf = dict_foreign_err_buf;
|
||||||
|
|
||||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||||
|
|
||||||
@@ -1850,9 +1862,29 @@ dict_foreign_add_to_cache(
|
|||||||
for_in_cache->foreign_index);
|
for_in_cache->foreign_index);
|
||||||
|
|
||||||
if (index == NULL) {
|
if (index == NULL) {
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s:\n"
|
||||||
|
"there is no index in referenced table which would contain\n"
|
||||||
|
"the columns as the first columns, or the data types in the\n"
|
||||||
|
"referenced table do not match to the ones in table. Constraint:\n",
|
||||||
|
for_in_cache->foreign_table_name);
|
||||||
|
dict_print_info_on_foreign_key_in_create_format(
|
||||||
|
for_in_cache, buf + strlen(buf));
|
||||||
|
if (for_in_cache->foreign_index) {
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"\nThe index in the foreign key in table is %.500s\n"
|
||||||
|
"See http://www.innodb.com/ibman.html about correct foreign key definition.\n",
|
||||||
|
for_in_cache->foreign_index->name);
|
||||||
|
}
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
if (for_in_cache == foreign) {
|
if (for_in_cache == foreign) {
|
||||||
mem_heap_free(foreign->heap);
|
mem_heap_free(foreign->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1871,6 +1903,25 @@ dict_foreign_add_to_cache(
|
|||||||
for_in_cache->referenced_index);
|
for_in_cache->referenced_index);
|
||||||
|
|
||||||
if (index == NULL) {
|
if (index == NULL) {
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s:\n"
|
||||||
|
"there is no index in the table which would contain\n"
|
||||||
|
"the columns as the first columns, or the data types in the\n"
|
||||||
|
"table do not match to the ones in the referenced table. Constraint:\n",
|
||||||
|
for_in_cache->foreign_table_name);
|
||||||
|
dict_print_info_on_foreign_key_in_create_format(
|
||||||
|
for_in_cache, buf + strlen(buf));
|
||||||
|
if (for_in_cache->foreign_index) {
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"\nIndex of the foreign key in the referenced table is %.500s\n"
|
||||||
|
"See http://www.innodb.com/ibman.html about correct foreign key definition.\n",
|
||||||
|
for_in_cache->referenced_index->name);
|
||||||
|
}
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
if (for_in_cache == foreign) {
|
if (for_in_cache == foreign) {
|
||||||
if (added_to_referenced_list) {
|
if (added_to_referenced_list) {
|
||||||
UT_LIST_REMOVE(referenced_list,
|
UT_LIST_REMOVE(referenced_list,
|
||||||
@@ -2141,18 +2192,21 @@ dict_scan_table_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Skips one 'word', like an id. For the lexical definition of 'word', see the
|
Scans an id. For the lexical definition of an 'id', see the code below.
|
||||||
code below. */
|
Strips backquotes from around the id. */
|
||||||
static
|
static
|
||||||
char*
|
char*
|
||||||
dict_skip_word(
|
dict_scan_id(
|
||||||
/*===========*/
|
/*=========*/
|
||||||
/* out: scanned to */
|
/* out: scanned to */
|
||||||
char* ptr, /* in: scanned to */
|
char* ptr, /* in: scanned to */
|
||||||
ibool* success)/* out: TRUE if success, FALSE if just spaces left in
|
char** start, /* out: start of the id; NULL if no id was
|
||||||
string */
|
scannable */
|
||||||
|
ulint* len) /* out: length of the id */
|
||||||
{
|
{
|
||||||
*success = FALSE;
|
ibool scanned_backquote = FALSE;
|
||||||
|
|
||||||
|
*start = NULL;
|
||||||
|
|
||||||
while (isspace(*ptr)) {
|
while (isspace(*ptr)) {
|
||||||
ptr++;
|
ptr++;
|
||||||
@@ -2164,20 +2218,58 @@ dict_skip_word(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*ptr == '`') {
|
if (*ptr == '`') {
|
||||||
|
scanned_backquote = TRUE;
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
|
*start = ptr;
|
||||||
&& *ptr != '\0') {
|
|
||||||
|
while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != ')'
|
||||||
|
&& *ptr != '\0' && *ptr != '`') {
|
||||||
|
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*success = TRUE;
|
*len = (ulint) (ptr - *start);
|
||||||
|
|
||||||
|
if (scanned_backquote) {
|
||||||
|
if (*ptr == '`') {
|
||||||
|
ptr++;
|
||||||
|
} else {
|
||||||
|
/* Syntax error */
|
||||||
|
*start = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(ptr);
|
return(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Skips one id. */
|
||||||
|
static
|
||||||
|
char*
|
||||||
|
dict_skip_word(
|
||||||
|
/*===========*/
|
||||||
|
/* out: scanned to */
|
||||||
|
char* ptr, /* in: scanned to */
|
||||||
|
ibool* success)/* out: TRUE if success, FALSE if just spaces left in
|
||||||
|
string or a syntax error */
|
||||||
|
{
|
||||||
|
char* start;
|
||||||
|
ulint len;
|
||||||
|
|
||||||
|
*success = FALSE;
|
||||||
|
|
||||||
|
ptr = dict_scan_id(ptr, &start, &len);
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
*success = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef currentlynotused
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Returns the number of opening brackets '(' subtracted by the number
|
Returns the number of opening brackets '(' subtracted by the number
|
||||||
of closing brackets ')' between string and ptr. */
|
of closing brackets ')' between string and ptr. */
|
||||||
@@ -2204,6 +2296,106 @@ dict_bracket_count(
|
|||||||
|
|
||||||
return(count);
|
return(count);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Removes MySQL comments from an SQL string. A comment is either
|
||||||
|
(a) '#' to the end of the line,
|
||||||
|
(b) '--<space>' to the end of the line, or
|
||||||
|
(c) '<slash><asterisk>' till the next '<asterisk><slash>' (like the familiar
|
||||||
|
C comment syntax). */
|
||||||
|
static
|
||||||
|
char*
|
||||||
|
dict_strip_comments(
|
||||||
|
/*================*/
|
||||||
|
/* out, own: SQL string stripped from
|
||||||
|
comments; the caller must free this
|
||||||
|
with mem_free()! */
|
||||||
|
char* sql_string) /* in: SQL string */
|
||||||
|
{
|
||||||
|
char* str;
|
||||||
|
char* sptr;
|
||||||
|
char* ptr;
|
||||||
|
|
||||||
|
str = mem_alloc(strlen(sql_string) + 1);
|
||||||
|
|
||||||
|
sptr = sql_string;
|
||||||
|
ptr = str;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (*sptr == '\0') {
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
return(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*sptr == '#'
|
||||||
|
|| (strlen(sptr) >= 3 && 0 == memcmp("-- ", sptr, 3))) {
|
||||||
|
for (;;) {
|
||||||
|
/* In Unix a newline is 0x0D while in Windows
|
||||||
|
it is 0x0A followed by 0x0D */
|
||||||
|
|
||||||
|
if (*sptr == (char)0x0A
|
||||||
|
|| *sptr == (char)0x0D
|
||||||
|
|| *sptr == '\0') {
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(sptr) >= 2 && *sptr == '/' && *(sptr + 1) == '*') {
|
||||||
|
for (;;) {
|
||||||
|
if (strlen(sptr) >= 2
|
||||||
|
&& *sptr == '*' && *(sptr + 1) == '/') {
|
||||||
|
|
||||||
|
sptr += 2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*sptr == '\0') {
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = *sptr;
|
||||||
|
|
||||||
|
ptr++;
|
||||||
|
sptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Reports a simple foreign key create clause syntax error. */
|
||||||
|
static
|
||||||
|
void
|
||||||
|
dict_foreign_report_syntax_err(
|
||||||
|
/*===========================*/
|
||||||
|
char* name, /* in: table name */
|
||||||
|
char* start_of_latest_foreign,/* in: start of the foreign key clause
|
||||||
|
in the SQL string */
|
||||||
|
char* ptr) /* in: place of the syntax error */
|
||||||
|
{
|
||||||
|
char* buf = dict_foreign_err_buf;
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
|
||||||
|
"Syntax error close to:\n%.500s\n", name, start_of_latest_foreign, ptr);
|
||||||
|
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Scans a table create SQL string and adds to the data dictionary the foreign
|
Scans a table create SQL string and adds to the data dictionary the foreign
|
||||||
@@ -2211,10 +2403,10 @@ key constraints declared in the string. This function should be called after
|
|||||||
the indexes for a table have been created. Each foreign key constraint must
|
the indexes for a table have been created. Each foreign key constraint must
|
||||||
be accompanied with indexes in both participating tables. The indexes are
|
be accompanied with indexes in both participating tables. The indexes are
|
||||||
allowed to contain more fields than mentioned in the constraint. */
|
allowed to contain more fields than mentioned in the constraint. */
|
||||||
|
static
|
||||||
ulint
|
ulint
|
||||||
dict_create_foreign_constraints(
|
dict_create_foreign_constraints_low(
|
||||||
/*============================*/
|
/*================================*/
|
||||||
/* out: error code or DB_SUCCESS */
|
/* out: error code or DB_SUCCESS */
|
||||||
trx_t* trx, /* in: transaction */
|
trx_t* trx, /* in: transaction */
|
||||||
char* sql_string, /* in: table create or ALTER TABLE
|
char* sql_string, /* in: table create or ALTER TABLE
|
||||||
@@ -2231,6 +2423,8 @@ dict_create_foreign_constraints(
|
|||||||
dict_index_t* index;
|
dict_index_t* index;
|
||||||
dict_foreign_t* foreign;
|
dict_foreign_t* foreign;
|
||||||
char* ptr = sql_string;
|
char* ptr = sql_string;
|
||||||
|
char* start_of_latest_foreign = sql_string;
|
||||||
|
char* buf = dict_foreign_err_buf;
|
||||||
ibool success;
|
ibool success;
|
||||||
ulint error;
|
ulint error;
|
||||||
ulint i;
|
ulint i;
|
||||||
@@ -2248,6 +2442,15 @@ dict_create_foreign_constraints(
|
|||||||
table = dict_table_get_low(name);
|
table = dict_table_get_low(name);
|
||||||
|
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s.\n"
|
||||||
|
"Cannot find the table from the internal data dictionary of InnoDB.\n"
|
||||||
|
"Create table statement:\n%.2000\n", name, sql_string);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_ERROR);
|
return(DB_ERROR);
|
||||||
}
|
}
|
||||||
loop:
|
loop:
|
||||||
@@ -2263,6 +2466,8 @@ loop:
|
|||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start_of_latest_foreign = ptr;
|
||||||
|
|
||||||
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
|
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
|
||||||
|
|
||||||
if (!isspace(*ptr)) {
|
if (!isspace(*ptr)) {
|
||||||
@@ -2283,13 +2488,19 @@ loop:
|
|||||||
ptr = dict_skip_word(ptr, &success);
|
ptr = dict_skip_word(ptr, &success);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
dict_foreign_report_syntax_err(name,
|
||||||
|
start_of_latest_foreign, ptr);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = dict_accept(ptr, (char *) "(", &success);
|
ptr = dict_accept(ptr, (char *) "(", &success);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
/* We do not flag a syntax error here because in an
|
||||||
|
ALTER TABLE we may also have DROP FOREIGN KEY abc */
|
||||||
|
|
||||||
|
goto loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2300,6 +2511,15 @@ col_loop1:
|
|||||||
ptr = dict_scan_col(ptr, &success, table, columns + i,
|
ptr = dict_scan_col(ptr, &success, table, columns + i,
|
||||||
column_names + i, column_name_lens + i);
|
column_names + i, column_name_lens + i);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
|
||||||
|
"Cannot resolve column name close to:\n%.500s\n", name,
|
||||||
|
start_of_latest_foreign, ptr);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2314,6 +2534,8 @@ col_loop1:
|
|||||||
ptr = dict_accept(ptr, (char *) ")", &success);
|
ptr = dict_accept(ptr, (char *) ")", &success);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||||
|
ptr);
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2323,12 +2545,24 @@ col_loop1:
|
|||||||
index = dict_foreign_find_index(table, column_names, i, NULL);
|
index = dict_foreign_find_index(table, column_names, i, NULL);
|
||||||
|
|
||||||
if (!index) {
|
if (!index) {
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s:\n"
|
||||||
|
"There is no index in the table %.500s where the columns appear\n"
|
||||||
|
"as the first columns. Constraint:\n%.500s\n"
|
||||||
|
"See http://www.innodb.com/ibman.html for correct foreign key definition.\n",
|
||||||
|
name, name, start_of_latest_foreign);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = dict_accept(ptr, (char *) "REFERENCES", &success);
|
ptr = dict_accept(ptr, (char *) "REFERENCES", &success);
|
||||||
|
|
||||||
if (!success || !isspace(*ptr)) {
|
if (!success || !isspace(*ptr)) {
|
||||||
|
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||||
|
ptr);
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2358,6 +2592,15 @@ col_loop1:
|
|||||||
if (!success || (!referenced_table && trx->check_foreigns)) {
|
if (!success || (!referenced_table && trx->check_foreigns)) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
|
||||||
|
"Cannot resolve table name close to:\n"
|
||||||
|
"%.500s\n", name, start_of_latest_foreign, ptr);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2365,7 +2608,8 @@ col_loop1:
|
|||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||||
|
ptr);
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2380,6 +2624,15 @@ col_loop2:
|
|||||||
if (!success) {
|
if (!success) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s,\n%.500s\n"
|
||||||
|
"Cannot resolve column name close to:\n"
|
||||||
|
"%.500s\n", name, start_of_latest_foreign, ptr);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2394,6 +2647,8 @@ col_loop2:
|
|||||||
if (!success || foreign->n_fields != i) {
|
if (!success || foreign->n_fields != i) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
|
||||||
|
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||||
|
ptr);
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2416,9 +2671,10 @@ scan_on_conditions:
|
|||||||
ptr = dict_accept(ptr, "UPDATE", &success);
|
ptr = dict_accept(ptr, "UPDATE", &success);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
|
||||||
|
dict_foreign_report_syntax_err(name,
|
||||||
|
start_of_latest_foreign, ptr);
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2454,6 +2710,8 @@ scan_on_conditions:
|
|||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
dict_foreign_report_syntax_err(name,
|
||||||
|
start_of_latest_foreign, ptr);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
@@ -2471,7 +2729,8 @@ scan_on_conditions:
|
|||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||||
|
ptr);
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2479,7 +2738,8 @@ scan_on_conditions:
|
|||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||||
|
ptr);
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2493,6 +2753,15 @@ scan_on_conditions:
|
|||||||
|
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
|
||||||
|
"You have defined a SET NULL condition though some of the\n"
|
||||||
|
"columns is defined as NOT NULL.\n", name, start_of_latest_foreign);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2511,6 +2780,15 @@ try_find_index:
|
|||||||
|
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
|
||||||
|
"You have twice an ON DELETE clause or twice an ON UPDATE clause.\n",
|
||||||
|
name, start_of_latest_foreign);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2524,6 +2802,18 @@ try_find_index:
|
|||||||
foreign->foreign_index);
|
foreign->foreign_index);
|
||||||
if (!index) {
|
if (!index) {
|
||||||
dict_foreign_free(foreign);
|
dict_foreign_free(foreign);
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in foreign key constraint of table %.500s:\n"
|
||||||
|
"Cannot find an index in the referenced table where the\n"
|
||||||
|
"referenced columns appear as the first columns, or column types\n"
|
||||||
|
"in the table and the referenced table do not match for constraint:\n%.500s\n"
|
||||||
|
"See http://www.innodb.com/ibman.html for correct foreign key definition.\n",
|
||||||
|
name, start_of_latest_foreign);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -2564,6 +2854,165 @@ try_find_index:
|
|||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Scans a table create SQL string and adds to the data dictionary the foreign
|
||||||
|
key constraints declared in the string. This function should be called after
|
||||||
|
the indexes for a table have been created. Each foreign key constraint must
|
||||||
|
be accompanied with indexes in both participating tables. The indexes are
|
||||||
|
allowed to contain more fields than mentioned in the constraint. */
|
||||||
|
|
||||||
|
ulint
|
||||||
|
dict_create_foreign_constraints(
|
||||||
|
/*============================*/
|
||||||
|
/* out: error code or DB_SUCCESS */
|
||||||
|
trx_t* trx, /* in: transaction */
|
||||||
|
char* sql_string, /* in: table create or ALTER TABLE
|
||||||
|
statement where foreign keys are declared like:
|
||||||
|
FOREIGN KEY (a, b) REFERENCES table2(c, d),
|
||||||
|
table2 can be written also with the database
|
||||||
|
name before it: test.table2; the default
|
||||||
|
database id the database of parameter name */
|
||||||
|
char* name) /* in: table full name in the normalized form
|
||||||
|
database_name/table_name */
|
||||||
|
{
|
||||||
|
char* str;
|
||||||
|
ulint err;
|
||||||
|
|
||||||
|
str = dict_strip_comments(sql_string);
|
||||||
|
|
||||||
|
err = dict_create_foreign_constraints_low(trx, str, name);
|
||||||
|
|
||||||
|
mem_free(str);
|
||||||
|
|
||||||
|
return(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
|
||||||
|
|
||||||
|
ulint
|
||||||
|
dict_foreign_parse_drop_constraints(
|
||||||
|
/*================================*/
|
||||||
|
/* out: DB_SUCCESS or
|
||||||
|
DB_CANNOT_DROP_CONSTRAINT if
|
||||||
|
syntax error or the constraint
|
||||||
|
id does not match */
|
||||||
|
mem_heap_t* heap, /* in: heap from which we can
|
||||||
|
allocate memory */
|
||||||
|
trx_t* trx, /* in: transaction */
|
||||||
|
dict_table_t* table, /* in: table */
|
||||||
|
ulint* n, /* out: number of constraints
|
||||||
|
to drop */
|
||||||
|
char*** constraints_to_drop) /* out: id's of the
|
||||||
|
constraints to drop */
|
||||||
|
{
|
||||||
|
dict_foreign_t* foreign;
|
||||||
|
ibool success;
|
||||||
|
char* str;
|
||||||
|
char* ptr;
|
||||||
|
char* buf = dict_foreign_err_buf;
|
||||||
|
char* start;
|
||||||
|
char* id;
|
||||||
|
ulint len;
|
||||||
|
|
||||||
|
*n = 0;
|
||||||
|
|
||||||
|
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
|
||||||
|
|
||||||
|
str = dict_strip_comments(*(trx->mysql_query_str));
|
||||||
|
ptr = str;
|
||||||
|
|
||||||
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||||
|
loop:
|
||||||
|
ptr = dict_scan_to(ptr, (char *) "DROP");
|
||||||
|
|
||||||
|
if (*ptr == '\0') {
|
||||||
|
ut_a(*n < 1000);
|
||||||
|
|
||||||
|
mem_free(str);
|
||||||
|
|
||||||
|
return(DB_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = dict_accept(ptr, (char *) "DROP", &success);
|
||||||
|
|
||||||
|
if (!isspace(*ptr)) {
|
||||||
|
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = dict_accept(ptr, (char *) "KEY", &success);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
|
||||||
|
goto syntax_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = dict_scan_id(ptr, &start, &len);
|
||||||
|
|
||||||
|
if (start == NULL) {
|
||||||
|
|
||||||
|
goto syntax_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = mem_heap_alloc(heap, len + 1);
|
||||||
|
ut_memcpy(id, start, len);
|
||||||
|
id[len] = '\0';
|
||||||
|
(*constraints_to_drop)[*n] = id;
|
||||||
|
(*n)++;
|
||||||
|
|
||||||
|
/* Look for the given constraint id */
|
||||||
|
|
||||||
|
foreign = UT_LIST_GET_FIRST(table->foreign_list);
|
||||||
|
|
||||||
|
while (foreign != NULL) {
|
||||||
|
if (0 == ut_strcmp(foreign->id, id)) {
|
||||||
|
|
||||||
|
/* Found */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foreign == NULL) {
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Error in dropping of a foreign key constraint of table %.500s,\n"
|
||||||
|
"just before:\n%s\n in SQL command\n%s\nCannot find a constraint with the\n"
|
||||||
|
"given id %s.\n", table->name, ptr, str, id);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
|
mem_free(str);
|
||||||
|
|
||||||
|
return(DB_CANNOT_DROP_CONSTRAINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto loop;
|
||||||
|
|
||||||
|
syntax_error:
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" Syntax error in dropping of a foreign key constraint of table %.500s,\n"
|
||||||
|
"close to:\n%s\n in SQL command\n%s\n", table->name, ptr, str);
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
|
mem_free(str);
|
||||||
|
|
||||||
|
return(DB_CANNOT_DROP_CONSTRAINT);
|
||||||
|
}
|
||||||
|
|
||||||
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
|
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -3285,7 +3734,6 @@ dict_index_print_low(
|
|||||||
n_vals = index->stat_n_diff_key_vals[1];
|
n_vals = index->stat_n_diff_key_vals[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
" INDEX: name %s, table name %s, id %lu %lu, fields %lu/%lu, type %lu\n",
|
" INDEX: name %s, table name %s, id %lu %lu, fields %lu/%lu, type %lu\n",
|
||||||
index->name, index->table_name,
|
index->name, index->table_name,
|
||||||
@@ -3327,43 +3775,27 @@ dict_field_print_low(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Sprintfs to a string info on foreign keys of a table in a format suitable
|
Sprintfs to a string info on a foreign key of a table in a format suitable
|
||||||
for CREATE TABLE. */
|
for CREATE TABLE. */
|
||||||
static
|
|
||||||
void
|
char*
|
||||||
dict_print_info_on_foreign_keys_in_create_format(
|
dict_print_info_on_foreign_key_in_create_format(
|
||||||
/*=============================================*/
|
/*============================================*/
|
||||||
char* buf, /* in: auxiliary buffer */
|
/* out: how far in buf we printed */
|
||||||
char* str, /* in/out: pointer to a string */
|
dict_foreign_t* foreign,/* in: foreign key constraint */
|
||||||
ulint len, /* in: str has to be a buffer at least
|
char* buf) /* in: buffer of at least 5000 bytes */
|
||||||
len + 5000 bytes */
|
|
||||||
dict_table_t* table) /* in: table */
|
|
||||||
{
|
{
|
||||||
|
char* buf2 = buf;
|
||||||
dict_foreign_t* foreign;
|
|
||||||
ulint i;
|
ulint i;
|
||||||
char* buf2;
|
|
||||||
|
|
||||||
buf2 = buf;
|
|
||||||
|
|
||||||
mutex_enter(&(dict_sys->mutex));
|
|
||||||
|
|
||||||
foreign = UT_LIST_GET_FIRST(table->foreign_list);
|
|
||||||
|
|
||||||
if (foreign == NULL) {
|
|
||||||
mutex_exit(&(dict_sys->mutex));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (foreign != NULL) {
|
|
||||||
buf2 += sprintf(buf2, ",\n FOREIGN KEY (");
|
|
||||||
|
|
||||||
|
buf2 += sprintf(buf2, ",\n CONSTRAINT `%s` FOREIGN KEY (",
|
||||||
|
foreign->id);
|
||||||
for (i = 0; i < foreign->n_fields; i++) {
|
for (i = 0; i < foreign->n_fields; i++) {
|
||||||
if ((ulint)(buf2 - buf) >= len) {
|
if ((ulint)(buf2 - buf) >= 4000) {
|
||||||
|
|
||||||
goto no_space;
|
goto no_space;
|
||||||
}
|
}
|
||||||
buf2 += sprintf(buf2, "`%s`",
|
buf2 += sprintf(buf2, "`%.250s`",
|
||||||
foreign->foreign_col_names[i]);
|
foreign->foreign_col_names[i]);
|
||||||
|
|
||||||
if (i + 1 < foreign->n_fields) {
|
if (i + 1 < foreign->n_fields) {
|
||||||
@@ -3371,15 +3803,15 @@ dict_print_info_on_foreign_keys_in_create_format(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict_tables_have_same_db(table->name,
|
if (dict_tables_have_same_db(foreign->foreign_table_name,
|
||||||
foreign->referenced_table_name)) {
|
foreign->referenced_table_name)) {
|
||||||
/* Do not print the database name of the referenced
|
/* Do not print the database name of the referenced
|
||||||
table */
|
table */
|
||||||
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
|
buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
|
||||||
dict_remove_db_name(
|
dict_remove_db_name(
|
||||||
foreign->referenced_table_name));
|
foreign->referenced_table_name));
|
||||||
} else {
|
} else {
|
||||||
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
|
buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
|
||||||
foreign->referenced_table_name);
|
foreign->referenced_table_name);
|
||||||
/* Change the '/' in the table name to '.' */
|
/* Change the '/' in the table name to '.' */
|
||||||
|
|
||||||
@@ -3394,10 +3826,11 @@ dict_print_info_on_foreign_keys_in_create_format(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < foreign->n_fields; i++) {
|
for (i = 0; i < foreign->n_fields; i++) {
|
||||||
if ((ulint)(buf2 - buf) >= len) {
|
if ((ulint)(buf2 - buf) >= 4000) {
|
||||||
|
|
||||||
goto no_space;
|
goto no_space;
|
||||||
}
|
}
|
||||||
buf2 += sprintf(buf2, "`%s`",
|
buf2 += sprintf(buf2, "`%.250s`",
|
||||||
foreign->referenced_col_names[i]);
|
foreign->referenced_col_names[i]);
|
||||||
if (i + 1 < foreign->n_fields) {
|
if (i + 1 < foreign->n_fields) {
|
||||||
buf2 += sprintf(buf2, ", ");
|
buf2 += sprintf(buf2, ", ");
|
||||||
@@ -3430,6 +3863,47 @@ dict_print_info_on_foreign_keys_in_create_format(
|
|||||||
buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
|
buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
no_space:
|
||||||
|
return(buf2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
Sprintfs to a string info on foreign keys of a table in a format suitable
|
||||||
|
for CREATE TABLE. */
|
||||||
|
static
|
||||||
|
void
|
||||||
|
dict_print_info_on_foreign_keys_in_create_format(
|
||||||
|
/*=============================================*/
|
||||||
|
char* buf, /* in: auxiliary buffer */
|
||||||
|
char* str, /* in/out: pointer to a string */
|
||||||
|
ulint len, /* in: buf has to be a buffer of at least
|
||||||
|
len + 5000 bytes; str must have at least
|
||||||
|
len + 1 bytes */
|
||||||
|
dict_table_t* table) /* in: table */
|
||||||
|
{
|
||||||
|
dict_foreign_t* foreign;
|
||||||
|
char* buf2;
|
||||||
|
|
||||||
|
buf2 = buf;
|
||||||
|
|
||||||
|
mutex_enter(&(dict_sys->mutex));
|
||||||
|
|
||||||
|
foreign = UT_LIST_GET_FIRST(table->foreign_list);
|
||||||
|
|
||||||
|
if (foreign == NULL) {
|
||||||
|
mutex_exit(&(dict_sys->mutex));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (foreign != NULL) {
|
||||||
|
if ((ulint)(buf2 - buf) >= len) {
|
||||||
|
goto no_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf2 = dict_print_info_on_foreign_key_in_create_format(
|
||||||
|
foreign, buf2);
|
||||||
|
|
||||||
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
|
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
|
||||||
}
|
}
|
||||||
no_space:
|
no_space:
|
||||||
@@ -3489,7 +3963,7 @@ dict_print_info_on_foreign_keys(
|
|||||||
goto no_space;
|
goto no_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf2 += sprintf(buf2, "%s",
|
buf2 += sprintf(buf2, "%.500s",
|
||||||
foreign->foreign_col_names[i]);
|
foreign->foreign_col_names[i]);
|
||||||
|
|
||||||
if (i + 1 < foreign->n_fields) {
|
if (i + 1 < foreign->n_fields) {
|
||||||
@@ -3497,14 +3971,14 @@ dict_print_info_on_foreign_keys(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf2 += sprintf(buf2, ") REFER %s(",
|
buf2 += sprintf(buf2, ") REFER %.500s(",
|
||||||
foreign->referenced_table_name);
|
foreign->referenced_table_name);
|
||||||
|
|
||||||
for (i = 0; i < foreign->n_fields; i++) {
|
for (i = 0; i < foreign->n_fields; i++) {
|
||||||
if ((ulint)(buf2 - buf) >= len) {
|
if ((ulint)(buf2 - buf) >= len) {
|
||||||
goto no_space;
|
goto no_space;
|
||||||
}
|
}
|
||||||
buf2 += sprintf(buf2, "%s",
|
buf2 += sprintf(buf2, "%.500s",
|
||||||
foreign->referenced_col_names[i]);
|
foreign->referenced_col_names[i]);
|
||||||
if (i + 1 < foreign->n_fields) {
|
if (i + 1 < foreign->n_fields) {
|
||||||
buf2 += sprintf(buf2, " ");
|
buf2 += sprintf(buf2, " ");
|
||||||
|
@@ -456,7 +456,7 @@ dict_load_indexes(
|
|||||||
ut_ad(len == 8);
|
ut_ad(len == 8);
|
||||||
id = mach_read_from_8(field);
|
id = mach_read_from_8(field);
|
||||||
|
|
||||||
ut_a(0 == ut_strcmp("NAME",
|
ut_a(0 == ut_strcmp((char*)"NAME",
|
||||||
dict_field_get_col(
|
dict_field_get_col(
|
||||||
dict_index_get_nth_field(
|
dict_index_get_nth_field(
|
||||||
dict_table_get_first_index(sys_indexes), 4))->name));
|
dict_table_get_first_index(sys_indexes), 4))->name));
|
||||||
@@ -515,7 +515,7 @@ dict_load_indexes(
|
|||||||
&& ((type & DICT_CLUSTERED)
|
&& ((type & DICT_CLUSTERED)
|
||||||
|| ((table == dict_sys->sys_tables)
|
|| ((table == dict_sys->sys_tables)
|
||||||
&& (name_len == ut_strlen("ID_IND"))
|
&& (name_len == ut_strlen("ID_IND"))
|
||||||
&& (0 == ut_memcmp(name_buf, "ID_IND",
|
&& (0 == ut_memcmp(name_buf, (char*)"ID_IND",
|
||||||
name_len))))) {
|
name_len))))) {
|
||||||
|
|
||||||
/* The index was created in memory already in
|
/* The index was created in memory already in
|
||||||
@@ -566,6 +566,7 @@ dict_load_table(
|
|||||||
char* buf;
|
char* buf;
|
||||||
ulint space;
|
ulint space;
|
||||||
ulint n_cols;
|
ulint n_cols;
|
||||||
|
ulint err;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||||
@@ -674,8 +675,25 @@ dict_load_table(
|
|||||||
|
|
||||||
dict_load_indexes(table, heap);
|
dict_load_indexes(table, heap);
|
||||||
|
|
||||||
ut_a(DB_SUCCESS == dict_load_foreigns(table->name));
|
err = dict_load_foreigns(table->name);
|
||||||
|
/*
|
||||||
|
if (err != DB_SUCCESS) {
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
|
ut_print_timestamp(stderr);
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
" InnoDB: Error: could not make a foreign key definition to match\n"
|
||||||
|
"InnoDB: the foreign key table or the referenced table!\n"
|
||||||
|
"InnoDB: The data dictionary of InnoDB is corrupt. You may need to drop\n"
|
||||||
|
"InnoDB: and recreate the foreign key table or the referenced table.\n"
|
||||||
|
"InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n"
|
||||||
|
"InnoDB: Latest foreign key error printout:\n%s\n", dict_foreign_err_buf);
|
||||||
|
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
}
|
||||||
|
*/
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
return(table);
|
return(table);
|
||||||
@@ -978,8 +996,8 @@ dict_load_foreign(
|
|||||||
|
|
||||||
field = rec_get_nth_field(rec, 4, &len);
|
field = rec_get_nth_field(rec, 4, &len);
|
||||||
|
|
||||||
foreign->referenced_table_name = mem_heap_alloc(foreign->heap, 1 + len);
|
foreign->referenced_table_name = mem_heap_alloc(foreign->heap,
|
||||||
|
1 + len);
|
||||||
ut_memcpy(foreign->referenced_table_name, field, len);
|
ut_memcpy(foreign->referenced_table_name, field, len);
|
||||||
foreign->referenced_table_name[len] = '\0';
|
foreign->referenced_table_name[len] = '\0';
|
||||||
|
|
||||||
@@ -988,10 +1006,19 @@ dict_load_foreign(
|
|||||||
|
|
||||||
dict_load_foreign_cols(id, foreign);
|
dict_load_foreign_cols(id, foreign);
|
||||||
|
|
||||||
|
/* If the foreign table is not yet in the dictionary cache, we
|
||||||
|
have to load it so that we are able to make type comparisons
|
||||||
|
in the next function call. */
|
||||||
|
|
||||||
|
dict_table_get_low(foreign->foreign_table_name);
|
||||||
|
|
||||||
/* Note that there may already be a foreign constraint object in
|
/* Note that there may already be a foreign constraint object in
|
||||||
the dictionary cache for this constraint: then the following
|
the dictionary cache for this constraint: then the following
|
||||||
call only sets the pointers in it to point to the appropriate table
|
call only sets the pointers in it to point to the appropriate table
|
||||||
and index objects and frees the newly created object foreign. */
|
and index objects and frees the newly created object foreign.
|
||||||
|
Adding to the cache should always succeed since we are not creating
|
||||||
|
a new foreign key constraint but loading one from the data
|
||||||
|
dictionary. */
|
||||||
|
|
||||||
err = dict_foreign_add_to_cache(foreign);
|
err = dict_foreign_add_to_cache(foreign);
|
||||||
|
|
||||||
|
@@ -2420,17 +2420,22 @@ ibuf_delete_rec(
|
|||||||
fprintf(stderr, "InnoDB: ibuf cursor restoration fails!\n");
|
fprintf(stderr, "InnoDB: ibuf cursor restoration fails!\n");
|
||||||
fprintf(stderr, "InnoDB: ibuf record inserted to page %lu\n",
|
fprintf(stderr, "InnoDB: ibuf record inserted to page %lu\n",
|
||||||
page_no);
|
page_no);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
rec_print(btr_pcur_get_rec(pcur));
|
rec_print(btr_pcur_get_rec(pcur));
|
||||||
rec_print(pcur->old_rec);
|
rec_print(pcur->old_rec);
|
||||||
dtuple_print(search_tuple);
|
dtuple_print(search_tuple);
|
||||||
|
|
||||||
rec_print(page_rec_get_next(btr_pcur_get_rec(pcur)));
|
rec_print(page_rec_get_next(btr_pcur_get_rec(pcur)));
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
mtr_commit(mtr);
|
mtr_commit(mtr);
|
||||||
|
|
||||||
fprintf(stderr, "InnoDB: Validating insert buffer tree:\n");
|
fprintf(stderr, "InnoDB: Validating insert buffer tree:\n");
|
||||||
ut_a(btr_validate_tree(ibuf_data->index->tree));
|
ut_a(btr_validate_tree(ibuf_data->index->tree));
|
||||||
fprintf(stderr, "InnoDB: Ibuf tree ok\n");
|
|
||||||
|
fprintf(stderr, "InnoDB: ibuf tree ok\n");
|
||||||
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(success);
|
ut_a(success);
|
||||||
|
@@ -44,6 +44,8 @@ Created 5/24/1996 Heikki Tuuri
|
|||||||
#define DB_CORRUPTION 39 /* data structure corruption noticed */
|
#define DB_CORRUPTION 39 /* data structure corruption noticed */
|
||||||
#define DB_COL_APPEARS_TWICE_IN_INDEX 40 /* InnoDB cannot handle an index
|
#define DB_COL_APPEARS_TWICE_IN_INDEX 40 /* InnoDB cannot handle an index
|
||||||
where same column appears twice */
|
where same column appears twice */
|
||||||
|
#define DB_CANNOT_DROP_CONSTRAINT 40 /* dropping a foreign key constraint
|
||||||
|
from a table failed */
|
||||||
|
|
||||||
/* The following are partial failure codes */
|
/* The following are partial failure codes */
|
||||||
#define DB_FAIL 1000
|
#define DB_FAIL 1000
|
||||||
|
@@ -219,6 +219,24 @@ dict_create_foreign_constraints(
|
|||||||
char* name); /* in: table full name in the normalized form
|
char* name); /* in: table full name in the normalized form
|
||||||
database_name/table_name */
|
database_name/table_name */
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
|
||||||
|
|
||||||
|
ulint
|
||||||
|
dict_foreign_parse_drop_constraints(
|
||||||
|
/*================================*/
|
||||||
|
/* out: DB_SUCCESS or
|
||||||
|
DB_CANNOT_DROP_CONSTRAINT if
|
||||||
|
syntax error or the constraint
|
||||||
|
id does not match */
|
||||||
|
mem_heap_t* heap, /* in: heap from which we can
|
||||||
|
allocate memory */
|
||||||
|
trx_t* trx, /* in: transaction */
|
||||||
|
dict_table_t* table, /* in: table */
|
||||||
|
ulint* n, /* out: number of constraints
|
||||||
|
to drop */
|
||||||
|
char*** constraints_to_drop); /* out: id's of the
|
||||||
|
constraints to drop */
|
||||||
|
/**************************************************************************
|
||||||
Returns a table object and memoryfixes it. NOTE! This is a high-level
|
Returns a table object and memoryfixes it. NOTE! This is a high-level
|
||||||
function to be used mainly from outside the 'dict' directory. Inside this
|
function to be used mainly from outside the 'dict' directory. Inside this
|
||||||
directory dict_table_get_low is usually the appropriate function. */
|
directory dict_table_get_low is usually the appropriate function. */
|
||||||
@@ -333,6 +351,16 @@ dict_print_info_on_foreign_keys(
|
|||||||
char* str, /* in/out: pointer to a string */
|
char* str, /* in/out: pointer to a string */
|
||||||
ulint len, /* in: space in str available for info */
|
ulint len, /* in: space in str available for info */
|
||||||
dict_table_t* table); /* in: table */
|
dict_table_t* table); /* in: table */
|
||||||
|
/**************************************************************************
|
||||||
|
Sprintfs to a string info on a foreign key of a table in a format suitable
|
||||||
|
for CREATE TABLE. */
|
||||||
|
|
||||||
|
char*
|
||||||
|
dict_print_info_on_foreign_key_in_create_format(
|
||||||
|
/*============================================*/
|
||||||
|
/* out: how far in buf we printed */
|
||||||
|
dict_foreign_t* foreign,/* in: foreign key constraint */
|
||||||
|
char* buf); /* in: buffer of at least 5000 bytes */
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
Gets the first index on the table (the clustered index). */
|
Gets the first index on the table (the clustered index). */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
@@ -808,6 +836,13 @@ void
|
|||||||
dict_mutex_exit_for_mysql(void);
|
dict_mutex_exit_for_mysql(void);
|
||||||
/*===========================*/
|
/*===========================*/
|
||||||
|
|
||||||
|
/* The following len must be at least 10000 bytes! */
|
||||||
|
#define DICT_FOREIGN_ERR_BUF_LEN 10000
|
||||||
|
|
||||||
|
/* Buffer for storing detailed information about the latest foreig key
|
||||||
|
error */
|
||||||
|
extern char* dict_foreign_err_buf;
|
||||||
|
extern mutex_t dict_foreign_err_mutex; /* mutex protecting the buffer */
|
||||||
|
|
||||||
extern dict_sys_t* dict_sys; /* the dictionary system */
|
extern dict_sys_t* dict_sys; /* the dictionary system */
|
||||||
extern rw_lock_t dict_operation_lock;
|
extern rw_lock_t dict_operation_lock;
|
||||||
|
@@ -35,7 +35,6 @@ row_ins_check_foreign_constraint(
|
|||||||
dictionary cache if they exist at all */
|
dictionary cache if they exist at all */
|
||||||
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
|
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
|
||||||
table, else the referenced table */
|
table, else the referenced table */
|
||||||
dict_index_t* index, /* in: index in table */
|
|
||||||
dtuple_t* entry, /* in: index entry for index */
|
dtuple_t* entry, /* in: index entry for index */
|
||||||
que_thr_t* thr); /* in: query thread */
|
que_thr_t* thr); /* in: query thread */
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@@ -3092,8 +3092,7 @@ lock_deadlock_recursive(
|
|||||||
err_buf += strlen(err_buf);
|
err_buf += strlen(err_buf);
|
||||||
|
|
||||||
err_buf += sprintf(err_buf,
|
err_buf += sprintf(err_buf,
|
||||||
" LATEST DETECTED DEADLOCK:\n"
|
"\n*** (1) TRANSACTION:\n");
|
||||||
"*** (1) TRANSACTION:\n");
|
|
||||||
|
|
||||||
trx_print(err_buf, wait_lock->trx);
|
trx_print(err_buf, wait_lock->trx);
|
||||||
err_buf += strlen(err_buf);
|
err_buf += strlen(err_buf);
|
||||||
@@ -3935,24 +3934,15 @@ lock_print_info(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf += sprintf(buf, "Trx id counter %lu %lu\n",
|
|
||||||
ut_dulint_get_high(trx_sys->max_trx_id),
|
|
||||||
ut_dulint_get_low(trx_sys->max_trx_id));
|
|
||||||
|
|
||||||
buf += sprintf(buf,
|
|
||||||
"Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
|
|
||||||
ut_dulint_get_high(purge_sys->purge_trx_no),
|
|
||||||
ut_dulint_get_low(purge_sys->purge_trx_no),
|
|
||||||
ut_dulint_get_high(purge_sys->purge_undo_no),
|
|
||||||
ut_dulint_get_low(purge_sys->purge_undo_no));
|
|
||||||
|
|
||||||
lock_mutex_enter_kernel();
|
lock_mutex_enter_kernel();
|
||||||
|
|
||||||
buf += sprintf(buf,
|
|
||||||
"Total number of lock structs in row lock hash table %lu\n",
|
|
||||||
lock_get_n_rec_locks());
|
|
||||||
if (lock_deadlock_found) {
|
if (lock_deadlock_found) {
|
||||||
|
|
||||||
|
buf += sprintf(buf,
|
||||||
|
"------------------------\n"
|
||||||
|
"LATEST DETECTED DEADLOCK\n"
|
||||||
|
"------------------------\n");
|
||||||
|
|
||||||
if ((ulint)(buf_end - buf)
|
if ((ulint)(buf_end - buf)
|
||||||
< 100 + strlen(lock_latest_err_buf)) {
|
< 100 + strlen(lock_latest_err_buf)) {
|
||||||
|
|
||||||
@@ -3972,6 +3962,26 @@ lock_print_info(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf += sprintf(buf,
|
||||||
|
"------------\n"
|
||||||
|
"TRANSACTIONS\n"
|
||||||
|
"------------\n");
|
||||||
|
|
||||||
|
buf += sprintf(buf, "Trx id counter %lu %lu\n",
|
||||||
|
ut_dulint_get_high(trx_sys->max_trx_id),
|
||||||
|
ut_dulint_get_low(trx_sys->max_trx_id));
|
||||||
|
|
||||||
|
buf += sprintf(buf,
|
||||||
|
"Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
|
||||||
|
ut_dulint_get_high(purge_sys->purge_trx_no),
|
||||||
|
ut_dulint_get_low(purge_sys->purge_trx_no),
|
||||||
|
ut_dulint_get_high(purge_sys->purge_undo_no),
|
||||||
|
ut_dulint_get_low(purge_sys->purge_undo_no));
|
||||||
|
|
||||||
|
buf += sprintf(buf,
|
||||||
|
"Total number of lock structs in row lock hash table %lu\n",
|
||||||
|
lock_get_n_rec_locks());
|
||||||
|
|
||||||
buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
|
buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
|
||||||
|
|
||||||
/* First print info on non-active transactions */
|
/* First print info on non-active transactions */
|
||||||
|
@@ -214,9 +214,14 @@ os_file_get_last_error(void)
|
|||||||
"InnoDB: the directory. It may also be you have created a subdirectory\n"
|
"InnoDB: the directory. It may also be you have created a subdirectory\n"
|
||||||
"InnoDB: of the same name as a data file.\n");
|
"InnoDB: of the same name as a data file.\n");
|
||||||
} else {
|
} else {
|
||||||
|
if (strerror((int)err) != NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
|
"InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err));
|
||||||
"InnoDB: what the error number means.\n");
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n"
|
||||||
|
"InnoDB: about operating system error numbers.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,9 +257,14 @@ os_file_get_last_error(void)
|
|||||||
"InnoDB: The error means mysqld does not have the access rights to\n"
|
"InnoDB: The error means mysqld does not have the access rights to\n"
|
||||||
"InnoDB: the directory.\n");
|
"InnoDB: the directory.\n");
|
||||||
} else {
|
} else {
|
||||||
|
if (strerror((int)err) != NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
|
"InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err));
|
||||||
"InnoDB: what the error number means or use the perror program of MySQL.\n");
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n"
|
||||||
|
"InnoDB: about operating system error numbers.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -437,6 +437,111 @@ row_ins_cascade_calc_update_vec(
|
|||||||
return(n_fields_updated);
|
return(n_fields_updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Reports a foreign key error associated with an update or a delete of a
|
||||||
|
parent table index entry. */
|
||||||
|
static
|
||||||
|
void
|
||||||
|
row_ins_foreign_report_err(
|
||||||
|
/*=======================*/
|
||||||
|
char* errstr, /* in: error string from the viewpoint
|
||||||
|
of the parent table */
|
||||||
|
que_thr_t* thr, /* in: query thread whose run_node
|
||||||
|
is an update node */
|
||||||
|
dict_foreign_t* foreign, /* in: foreign key constraint */
|
||||||
|
rec_t* rec, /* in: a matching index record in the
|
||||||
|
child table */
|
||||||
|
dtuple_t* entry) /* in: index entry in the parent
|
||||||
|
table */
|
||||||
|
{
|
||||||
|
char* buf = dict_foreign_err_buf;
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf), " Transaction:\n");
|
||||||
|
trx_print(buf + strlen(buf), thr_get_trx(thr));
|
||||||
|
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"Foreign key constraint fails for table %.500s:\n",
|
||||||
|
foreign->foreign_table_name);
|
||||||
|
dict_print_info_on_foreign_key_in_create_format(
|
||||||
|
foreign, buf + strlen(buf));
|
||||||
|
sprintf(buf + strlen(buf), "\n%s", errstr);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
" in parent table, in index %.500s tuple:\n",
|
||||||
|
foreign->referenced_index->name);
|
||||||
|
if (entry) {
|
||||||
|
dtuple_sprintf(buf + strlen(buf), 1000, entry);
|
||||||
|
}
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"\nBut in child table %.500s, in index %.500s, there is a record:\n",
|
||||||
|
foreign->foreign_table_name, foreign->foreign_index->name);
|
||||||
|
if (rec) {
|
||||||
|
rec_sprintf(buf + strlen(buf), 1000, rec);
|
||||||
|
}
|
||||||
|
sprintf(buf + strlen(buf), "\n");
|
||||||
|
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Reports a foreign key error to dict_foreign_err_buf when we are trying
|
||||||
|
to add an index entry to a child table. Note that the adding may be the result
|
||||||
|
of an update, too. */
|
||||||
|
static
|
||||||
|
void
|
||||||
|
row_ins_foreign_report_add_err(
|
||||||
|
/*===========================*/
|
||||||
|
que_thr_t* thr, /* in: query thread whose run_node
|
||||||
|
is an insert node */
|
||||||
|
dict_foreign_t* foreign, /* in: foreign key constraint */
|
||||||
|
rec_t* rec, /* in: a record in the parent table:
|
||||||
|
it does not match entry because we
|
||||||
|
have an error! */
|
||||||
|
dtuple_t* entry) /* in: index entry to insert in the
|
||||||
|
child table */
|
||||||
|
{
|
||||||
|
char* buf = dict_foreign_err_buf;
|
||||||
|
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf), " Transaction:\n");
|
||||||
|
trx_print(buf + strlen(buf), thr_get_trx(thr));
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"Foreign key constraint fails for table %.500s:\n",
|
||||||
|
foreign->foreign_table_name);
|
||||||
|
dict_print_info_on_foreign_key_in_create_format(
|
||||||
|
foreign, buf + strlen(buf));
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"\nTrying to add in child table, in index %.500s tuple:\n",
|
||||||
|
foreign->foreign_index->name);
|
||||||
|
if (entry) {
|
||||||
|
dtuple_sprintf(buf + strlen(buf), 1000, entry);
|
||||||
|
}
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"\nBut in parent table %.500s, in index %.500s,\n"
|
||||||
|
"the closest match we can find is record:\n",
|
||||||
|
foreign->referenced_table_name,
|
||||||
|
foreign->referenced_index->name);
|
||||||
|
if (rec && page_rec_is_supremum(rec)) {
|
||||||
|
/* If the cursor ended on a supremum record, it is better
|
||||||
|
to report the previous record in the error message, so that
|
||||||
|
the user gets a more descriptive error message. */
|
||||||
|
rec = page_rec_get_prev(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec) {
|
||||||
|
rec_sprintf(buf + strlen(buf), 1000, rec);
|
||||||
|
}
|
||||||
|
sprintf(buf + strlen(buf), "\n");
|
||||||
|
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Perform referential actions or checks when a parent row is deleted or updated
|
Perform referential actions or checks when a parent row is deleted or updated
|
||||||
and the constraint had an ON DELETE or ON UPDATE condition which was not
|
and the constraint had an ON DELETE or ON UPDATE condition which was not
|
||||||
@@ -453,6 +558,8 @@ row_ins_foreign_check_on_constraint(
|
|||||||
type is != 0 */
|
type is != 0 */
|
||||||
btr_pcur_t* pcur, /* in: cursor placed on a matching
|
btr_pcur_t* pcur, /* in: cursor placed on a matching
|
||||||
index record in the child table */
|
index record in the child table */
|
||||||
|
dtuple_t* entry, /* in: index entry in the parent
|
||||||
|
table */
|
||||||
mtr_t* mtr) /* in: mtr holding the latch of pcur
|
mtr_t* mtr) /* in: mtr holding the latch of pcur
|
||||||
page */
|
page */
|
||||||
{
|
{
|
||||||
@@ -506,6 +613,10 @@ row_ins_foreign_check_on_constraint(
|
|||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
row_ins_foreign_report_err((char*)"Trying to delete",
|
||||||
|
thr, foreign,
|
||||||
|
btr_pcur_get_rec(pcur), entry);
|
||||||
|
|
||||||
return(DB_ROW_IS_REFERENCED);
|
return(DB_ROW_IS_REFERENCED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,6 +634,10 @@ row_ins_foreign_check_on_constraint(
|
|||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
row_ins_foreign_report_err((char*)"Trying to update",
|
||||||
|
thr, foreign,
|
||||||
|
btr_pcur_get_rec(pcur), entry);
|
||||||
|
|
||||||
return(DB_ROW_IS_REFERENCED);
|
return(DB_ROW_IS_REFERENCED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,6 +695,10 @@ row_ins_foreign_check_on_constraint(
|
|||||||
|
|
||||||
err = DB_ROW_IS_REFERENCED;
|
err = DB_ROW_IS_REFERENCED;
|
||||||
|
|
||||||
|
row_ins_foreign_report_err(
|
||||||
|
(char*)"Trying an update, possibly causing a cyclic cascaded update\n"
|
||||||
|
"in the child table,", thr, foreign, btr_pcur_get_rec(pcur), entry);
|
||||||
|
|
||||||
goto nonstandard_exit_func;
|
goto nonstandard_exit_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,7 +928,6 @@ row_ins_check_foreign_constraint(
|
|||||||
dictionary cache if they exist at all */
|
dictionary cache if they exist at all */
|
||||||
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
|
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
|
||||||
table, else the referenced table */
|
table, else the referenced table */
|
||||||
dict_index_t* index __attribute__((unused)),/* in: index in table */
|
|
||||||
dtuple_t* entry, /* in: index entry for index */
|
dtuple_t* entry, /* in: index entry for index */
|
||||||
que_thr_t* thr) /* in: query thread */
|
que_thr_t* thr) /* in: query thread */
|
||||||
{
|
{
|
||||||
@@ -824,6 +942,7 @@ row_ins_check_foreign_constraint(
|
|||||||
int cmp;
|
int cmp;
|
||||||
ulint err;
|
ulint err;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
char* buf = dict_foreign_err_buf;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
run_again:
|
run_again:
|
||||||
@@ -884,6 +1003,25 @@ run_again:
|
|||||||
|
|
||||||
if (check_table == NULL) {
|
if (check_table == NULL) {
|
||||||
if (check_ref) {
|
if (check_ref) {
|
||||||
|
mutex_enter(&dict_foreign_err_mutex);
|
||||||
|
ut_sprintf_timestamp(buf);
|
||||||
|
sprintf(buf + strlen(buf), " Transaction:\n");
|
||||||
|
trx_print(buf + strlen(buf), thr_get_trx(thr));
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"Foreign key constraint fails for table %.500s:\n",
|
||||||
|
foreign->foreign_table_name);
|
||||||
|
dict_print_info_on_foreign_key_in_create_format(
|
||||||
|
foreign, buf + strlen(buf));
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"\nTrying to add to index %.500s tuple:\n", foreign->foreign_index->name);
|
||||||
|
dtuple_sprintf(buf + strlen(buf), 1000, entry);
|
||||||
|
sprintf(buf + strlen(buf),
|
||||||
|
"\nBut the parent table %.500s does not currently exist!\n",
|
||||||
|
foreign->referenced_table_name);
|
||||||
|
|
||||||
|
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
|
||||||
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
return(DB_NO_REFERENCED_ROW);
|
return(DB_NO_REFERENCED_ROW);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,7 +1087,8 @@ run_again:
|
|||||||
|
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
if (rec_get_deleted_flag(rec)) {
|
if (rec_get_deleted_flag(rec)) {
|
||||||
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
|
err = row_ins_set_shared_rec_lock(
|
||||||
|
LOCK_ORDINARY,
|
||||||
rec, check_index, thr);
|
rec, check_index, thr);
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
|
|
||||||
@@ -989,13 +1128,17 @@ run_again:
|
|||||||
|
|
||||||
err =
|
err =
|
||||||
row_ins_foreign_check_on_constraint(
|
row_ins_foreign_check_on_constraint(
|
||||||
thr, foreign, &pcur, &mtr);
|
thr, foreign, &pcur, entry,
|
||||||
|
&mtr);
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
row_ins_foreign_report_err(
|
||||||
|
(char*)"Trying to delete or update",
|
||||||
|
thr, foreign, rec, entry);
|
||||||
|
|
||||||
err = DB_ROW_IS_REFERENCED;
|
err = DB_ROW_IS_REFERENCED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1012,6 +1155,8 @@ run_again:
|
|||||||
|
|
||||||
if (check_ref) {
|
if (check_ref) {
|
||||||
err = DB_NO_REFERENCED_ROW;
|
err = DB_NO_REFERENCED_ROW;
|
||||||
|
row_ins_foreign_report_add_err(
|
||||||
|
thr, foreign, rec, entry);
|
||||||
} else {
|
} else {
|
||||||
err = DB_SUCCESS;
|
err = DB_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1025,6 +1170,9 @@ next_rec:
|
|||||||
|
|
||||||
if (!moved) {
|
if (!moved) {
|
||||||
if (check_ref) {
|
if (check_ref) {
|
||||||
|
rec = btr_pcur_get_rec(&pcur);
|
||||||
|
row_ins_foreign_report_add_err(
|
||||||
|
thr, foreign, rec, entry);
|
||||||
err = DB_NO_REFERENCED_ROW;
|
err = DB_NO_REFERENCED_ROW;
|
||||||
} else {
|
} else {
|
||||||
err = DB_SUCCESS;
|
err = DB_SUCCESS;
|
||||||
@@ -1100,7 +1248,7 @@ row_ins_check_foreign_constraints(
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = row_ins_check_foreign_constraint(TRUE, foreign,
|
err = row_ins_check_foreign_constraint(TRUE, foreign,
|
||||||
table, index, entry, thr);
|
table, entry, thr);
|
||||||
if (got_s_lock) {
|
if (got_s_lock) {
|
||||||
row_mysql_unfreeze_data_dictionary(trx);
|
row_mysql_unfreeze_data_dictionary(trx);
|
||||||
}
|
}
|
||||||
|
@@ -1156,7 +1156,7 @@ row_mysql_recover_tmp_table(
|
|||||||
return(DB_ERROR);
|
return(DB_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == ut_memcmp(ptr, "/rsql", 5)) {
|
if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) {
|
||||||
ptr++;
|
ptr++;
|
||||||
*ptr = '#';
|
*ptr = '#';
|
||||||
|
|
||||||
@@ -1281,9 +1281,9 @@ row_create_table_for_mysql(
|
|||||||
|
|
||||||
trx->op_info = (char *) "creating table";
|
trx->op_info = (char *) "creating table";
|
||||||
|
|
||||||
if (0 == ut_strcmp(table->name, "mysql/host")
|
if (0 == ut_strcmp(table->name, (char*)"mysql/host")
|
||||||
|| 0 == ut_strcmp(table->name, "mysql/user")
|
|| 0 == ut_strcmp(table->name, (char*)"mysql/user")
|
||||||
|| 0 == ut_strcmp(table->name, "mysql/db")) {
|
|| 0 == ut_strcmp(table->name, (char*)"mysql/db")) {
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
|
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
|
||||||
@@ -1303,7 +1303,7 @@ row_create_table_for_mysql(
|
|||||||
|
|
||||||
if (namelen >= keywordlen
|
if (namelen >= keywordlen
|
||||||
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
|
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
|
||||||
"_recover_innodb_tmp_table", keywordlen)) {
|
(char*)"_recover_innodb_tmp_table", keywordlen)) {
|
||||||
|
|
||||||
/* MySQL prevents accessing of tables whose name begins
|
/* MySQL prevents accessing of tables whose name begins
|
||||||
with #sql, that is temporary tables. If mysqld crashes in
|
with #sql, that is temporary tables. If mysqld crashes in
|
||||||
@@ -1371,7 +1371,7 @@ row_create_table_for_mysql(
|
|||||||
|
|
||||||
if (namelen >= keywordlen
|
if (namelen >= keywordlen
|
||||||
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
|
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
|
||||||
"innodb_mem_validate", keywordlen)) {
|
(char*)"innodb_mem_validate", keywordlen)) {
|
||||||
|
|
||||||
/* We define here a debugging feature intended for
|
/* We define here a debugging feature intended for
|
||||||
developers */
|
developers */
|
||||||
@@ -1481,7 +1481,7 @@ row_create_index_for_mysql(
|
|||||||
if (namelen >= keywordlen
|
if (namelen >= keywordlen
|
||||||
&& 0 == ut_memcmp(
|
&& 0 == ut_memcmp(
|
||||||
index->table_name + namelen - keywordlen,
|
index->table_name + namelen - keywordlen,
|
||||||
"_recover_innodb_tmp_table", keywordlen)) {
|
(char*)"_recover_innodb_tmp_table", keywordlen)) {
|
||||||
|
|
||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -1586,7 +1586,7 @@ row_table_add_foreign_constraints(
|
|||||||
if (namelen >= keywordlen
|
if (namelen >= keywordlen
|
||||||
&& 0 == ut_memcmp(
|
&& 0 == ut_memcmp(
|
||||||
name + namelen - keywordlen,
|
name + namelen - keywordlen,
|
||||||
"_recover_innodb_tmp_table", keywordlen)) {
|
(char*)"_recover_innodb_tmp_table", keywordlen)) {
|
||||||
|
|
||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -1808,7 +1808,6 @@ row_drop_table_for_mysql(
|
|||||||
ulint len;
|
ulint len;
|
||||||
ulint namelen;
|
ulint namelen;
|
||||||
ulint keywordlen;
|
ulint keywordlen;
|
||||||
ulint rounds = 0;
|
|
||||||
ibool locked_dictionary = FALSE;
|
ibool locked_dictionary = FALSE;
|
||||||
char buf[10000];
|
char buf[10000];
|
||||||
|
|
||||||
@@ -2155,7 +2154,7 @@ row_is_mysql_tmp_table_name(
|
|||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
for (i = 0; i <= ut_strlen(name) - 5; i++) {
|
for (i = 0; i <= ut_strlen(name) - 5; i++) {
|
||||||
if (ut_memcmp(name + i, "/#sql", 5) == 0) {
|
if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) {
|
||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
@@ -2177,12 +2176,16 @@ row_rename_table_for_mysql(
|
|||||||
{
|
{
|
||||||
dict_table_t* table;
|
dict_table_t* table;
|
||||||
que_thr_t* thr;
|
que_thr_t* thr;
|
||||||
que_t* graph;
|
que_t* graph = NULL;
|
||||||
ulint err;
|
ulint err;
|
||||||
char* str1;
|
char* str1;
|
||||||
char* str2;
|
char* str2;
|
||||||
char* str3;
|
char* str3;
|
||||||
|
mem_heap_t* heap = NULL;
|
||||||
|
char** constraints_to_drop = NULL;
|
||||||
|
ulint n_constraints_to_drop = 0;
|
||||||
ulint len;
|
ulint len;
|
||||||
|
ulint i;
|
||||||
char buf[10000];
|
char buf[10000];
|
||||||
|
|
||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
@@ -2201,9 +2204,9 @@ row_rename_table_for_mysql(
|
|||||||
return(DB_ERROR);
|
return(DB_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == ut_strcmp(new_name, "mysql/host")
|
if (0 == ut_strcmp(new_name, (char*)"mysql/host")
|
||||||
|| 0 == ut_strcmp(new_name, "mysql/user")
|
|| 0 == ut_strcmp(new_name, (char*)"mysql/user")
|
||||||
|| 0 == ut_strcmp(new_name, "mysql/db")) {
|
|| 0 == ut_strcmp(new_name, (char*)"mysql/db")) {
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
|
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
|
||||||
@@ -2217,6 +2220,19 @@ row_rename_table_for_mysql(
|
|||||||
trx->op_info = (char *) "renaming table";
|
trx->op_info = (char *) "renaming table";
|
||||||
trx_start_if_not_started(trx);
|
trx_start_if_not_started(trx);
|
||||||
|
|
||||||
|
/* Serialize data dictionary operations with dictionary mutex:
|
||||||
|
no deadlocks can occur then in these operations */
|
||||||
|
|
||||||
|
row_mysql_lock_data_dictionary(trx);
|
||||||
|
|
||||||
|
table = dict_table_get_low(old_name);
|
||||||
|
|
||||||
|
if (!table) {
|
||||||
|
err = DB_TABLE_NOT_FOUND;
|
||||||
|
|
||||||
|
goto funct_exit;
|
||||||
|
}
|
||||||
|
|
||||||
str1 = (char *)
|
str1 = (char *)
|
||||||
"PROCEDURE RENAME_TABLE_PROC () IS\n"
|
"PROCEDURE RENAME_TABLE_PROC () IS\n"
|
||||||
"new_table_name CHAR;\n"
|
"new_table_name CHAR;\n"
|
||||||
@@ -2229,14 +2245,43 @@ row_rename_table_for_mysql(
|
|||||||
|
|
||||||
if (row_is_mysql_tmp_table_name(new_name)) {
|
if (row_is_mysql_tmp_table_name(new_name)) {
|
||||||
|
|
||||||
/* We want to preserve the original foreign key
|
/* MySQL is doing an ALTER TABLE command and it renames the
|
||||||
constraint definitions despite the name change */
|
original table to a temporary table name. We want to preserve
|
||||||
|
the original foreign key constraint definitions despite the
|
||||||
|
name change. An exception is those constraints for which
|
||||||
|
the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/
|
||||||
|
|
||||||
str3 = (char*)
|
heap = mem_heap_create(100);
|
||||||
|
|
||||||
|
err = dict_foreign_parse_drop_constraints(heap, trx,
|
||||||
|
table,
|
||||||
|
&n_constraints_to_drop,
|
||||||
|
&constraints_to_drop);
|
||||||
|
if (err != DB_SUCCESS) {
|
||||||
|
|
||||||
|
goto funct_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
str3 = mem_heap_alloc(heap,
|
||||||
|
1000 + 500 * n_constraints_to_drop);
|
||||||
|
*str3 = '\0';
|
||||||
|
sprintf(str3,
|
||||||
"';\n"
|
"';\n"
|
||||||
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
|
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
|
||||||
"WHERE NAME = old_table_name;\n"
|
"WHERE NAME = old_table_name;\n");
|
||||||
"END;\n";
|
|
||||||
|
for (i = 0; i < n_constraints_to_drop; i++) {
|
||||||
|
sprintf(str3 + strlen(str3),
|
||||||
|
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n"
|
||||||
|
"DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n",
|
||||||
|
constraints_to_drop[i],
|
||||||
|
constraints_to_drop[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(str3 + strlen(str3),
|
||||||
|
"END;\n");
|
||||||
|
|
||||||
|
ut_a(strlen(str3) < 1000 + 500 * n_constraints_to_drop);
|
||||||
} else {
|
} else {
|
||||||
str3 = (char*)
|
str3 = (char*)
|
||||||
"';\n"
|
"';\n"
|
||||||
@@ -2267,13 +2312,6 @@ row_rename_table_for_mysql(
|
|||||||
|
|
||||||
ut_memcpy(buf + len, str3, ut_strlen(str3) + 1);
|
ut_memcpy(buf + len, str3, ut_strlen(str3) + 1);
|
||||||
|
|
||||||
/* Serialize data dictionary operations with dictionary mutex:
|
|
||||||
no deadlocks can occur then in these operations */
|
|
||||||
|
|
||||||
row_mysql_lock_data_dictionary(trx);
|
|
||||||
|
|
||||||
table = dict_table_get_low(old_name);
|
|
||||||
|
|
||||||
graph = pars_sql(buf);
|
graph = pars_sql(buf);
|
||||||
|
|
||||||
ut_a(graph);
|
ut_a(graph);
|
||||||
@@ -2283,12 +2321,6 @@ row_rename_table_for_mysql(
|
|||||||
|
|
||||||
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
|
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
|
||||||
|
|
||||||
if (!table) {
|
|
||||||
err = DB_TABLE_NOT_FOUND;
|
|
||||||
|
|
||||||
goto funct_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
|
ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
|
||||||
|
|
||||||
que_run_threads(thr);
|
que_run_threads(thr);
|
||||||
@@ -2329,6 +2361,13 @@ row_rename_table_for_mysql(
|
|||||||
|
|
||||||
if (row_is_mysql_tmp_table_name(old_name)) {
|
if (row_is_mysql_tmp_table_name(old_name)) {
|
||||||
|
|
||||||
|
/* MySQL is doing an ALTER TABLE command and it
|
||||||
|
renames the created temporary table to the name
|
||||||
|
of the original table. In the ALTER TABLE we maybe
|
||||||
|
created some FOREIGN KEY constraints for the temporary
|
||||||
|
table. But we want to load also the foreign key
|
||||||
|
constraint definitions for the original table name. */
|
||||||
|
|
||||||
err = dict_load_foreigns(new_name);
|
err = dict_load_foreigns(new_name);
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
@@ -2354,7 +2393,13 @@ row_rename_table_for_mysql(
|
|||||||
funct_exit:
|
funct_exit:
|
||||||
row_mysql_unlock_data_dictionary(trx);
|
row_mysql_unlock_data_dictionary(trx);
|
||||||
|
|
||||||
|
if (graph) {
|
||||||
que_graph_free(graph);
|
que_graph_free(graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heap) {
|
||||||
|
mem_heap_free(heap);
|
||||||
|
}
|
||||||
|
|
||||||
trx_commit_for_mysql(trx);
|
trx_commit_for_mysql(trx);
|
||||||
|
|
||||||
|
@@ -2601,6 +2601,24 @@ row_search_for_mysql(
|
|||||||
|
|
||||||
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
|
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
|
||||||
*/
|
*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/* PHASE 0: Release a possible s-latch we are holding on the
|
||||||
|
adaptive hash index latch if there is someone waiting behind */
|
||||||
|
|
||||||
|
if (trx->has_search_latch
|
||||||
|
&& btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
|
||||||
|
|
||||||
|
/* There is an x-latch request on the adaptive hash index:
|
||||||
|
release the s-latch to reduce starvation and wait for
|
||||||
|
BTR_SEA_TIMEOUT rounds before trying to keep it again over
|
||||||
|
calls from MySQL */
|
||||||
|
|
||||||
|
rw_lock_s_unlock(&btr_search_latch);
|
||||||
|
trx->has_search_latch = FALSE;
|
||||||
|
|
||||||
|
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------*/
|
/*-------------------------------------------------------------*/
|
||||||
/* PHASE 1: Try to pop the row from the prefetch cache */
|
/* PHASE 1: Try to pop the row from the prefetch cache */
|
||||||
|
|
||||||
@@ -2737,22 +2755,6 @@ row_search_for_mysql(
|
|||||||
and if we try that, we can deadlock on the adaptive
|
and if we try that, we can deadlock on the adaptive
|
||||||
hash index semaphore! */
|
hash index semaphore! */
|
||||||
|
|
||||||
if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
|
|
||||||
/* There is an x-latch request: release
|
|
||||||
a possible s-latch to reduce starvation
|
|
||||||
and wait for BTR_SEA_TIMEOUT rounds before
|
|
||||||
trying to keep it again over calls from
|
|
||||||
MySQL */
|
|
||||||
|
|
||||||
if (trx->has_search_latch) {
|
|
||||||
rw_lock_s_unlock(&btr_search_latch);
|
|
||||||
trx->has_search_latch = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
|
|
||||||
|
|
||||||
goto no_shortcut;
|
|
||||||
}
|
|
||||||
#ifndef UNIV_SEARCH_DEBUG
|
#ifndef UNIV_SEARCH_DEBUG
|
||||||
if (!trx->has_search_latch) {
|
if (!trx->has_search_latch) {
|
||||||
rw_lock_s_lock(&btr_search_latch);
|
rw_lock_s_lock(&btr_search_latch);
|
||||||
@@ -2810,7 +2812,6 @@ row_search_for_mysql(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
no_shortcut:
|
|
||||||
/*-------------------------------------------------------------*/
|
/*-------------------------------------------------------------*/
|
||||||
/* PHASE 3: Open or restore index cursor position */
|
/* PHASE 3: Open or restore index cursor position */
|
||||||
|
|
||||||
|
@@ -218,7 +218,7 @@ row_upd_check_references_constraints(
|
|||||||
being dropped while the check is running. */
|
being dropped while the check is running. */
|
||||||
|
|
||||||
err = row_ins_check_foreign_constraint(FALSE, foreign,
|
err = row_ins_check_foreign_constraint(FALSE, foreign,
|
||||||
table, index, entry, thr);
|
table, entry, thr);
|
||||||
|
|
||||||
if (foreign->foreign_table) {
|
if (foreign->foreign_table) {
|
||||||
mutex_enter(&(dict_sys->mutex));
|
mutex_enter(&(dict_sys->mutex));
|
||||||
|
@@ -1869,11 +1869,11 @@ retry:
|
|||||||
/* Go to wait for the event; when a thread leaves InnoDB it will
|
/* Go to wait for the event; when a thread leaves InnoDB it will
|
||||||
release this thread */
|
release this thread */
|
||||||
|
|
||||||
trx->op_info = "waiting in InnoDB queue";
|
trx->op_info = (char*)"waiting in InnoDB queue";
|
||||||
|
|
||||||
os_event_wait(slot->event);
|
os_event_wait(slot->event);
|
||||||
|
|
||||||
trx->op_info = "";
|
trx->op_info = (char*)"";
|
||||||
|
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
|
|
||||||
@@ -2346,9 +2346,19 @@ srv_sprintf_innodb_monitor(
|
|||||||
buf = buf + strlen(buf);
|
buf = buf + strlen(buf);
|
||||||
ut_a(buf < buf_end + 1500);
|
ut_a(buf < buf_end + 1500);
|
||||||
|
|
||||||
buf += sprintf(buf, "------------\n"
|
if (*dict_foreign_err_buf != '\0') {
|
||||||
"TRANSACTIONS\n"
|
buf += sprintf(buf,
|
||||||
"------------\n");
|
"------------------------\n"
|
||||||
|
"LATEST FOREIGN KEY ERROR\n"
|
||||||
|
"------------------------\n");
|
||||||
|
|
||||||
|
if (buf_end - buf > 6000) {
|
||||||
|
buf+= sprintf(buf, "%.4000s", dict_foreign_err_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_a(buf < buf_end + 1500);
|
||||||
|
|
||||||
lock_print_info(buf, buf_end);
|
lock_print_info(buf, buf_end);
|
||||||
buf = buf + strlen(buf);
|
buf = buf + strlen(buf);
|
||||||
|
|
||||||
|
@@ -204,7 +204,7 @@ ut_get_year_month_day(
|
|||||||
|
|
||||||
cal_tm_ptr = localtime(&tm);
|
cal_tm_ptr = localtime(&tm);
|
||||||
|
|
||||||
*year = (ulint)cal_tm_ptr->tm_year;
|
*year = (ulint)cal_tm_ptr->tm_year + 1900;
|
||||||
*month = (ulint)cal_tm_ptr->tm_mon + 1;
|
*month = (ulint)cal_tm_ptr->tm_mon + 1;
|
||||||
*day = (ulint)cal_tm_ptr->tm_mday;
|
*day = (ulint)cal_tm_ptr->tm_mday;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -47,7 +47,7 @@ sum(all a) count(all a) avg(all a) std(all a) bit_or(all a) bit_and(all a) min(a
|
|||||||
21 6 3.5000 1.7078 7 0 1 6 E
|
21 6 3.5000 1.7078 7 0 1 6 E
|
||||||
select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
|
select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
|
||||||
grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
|
grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
|
||||||
NULL 0 0 NULL NULL 0 0 NULL NULL
|
NULL NULL 0 NULL NULL 0 0 NULL NULL
|
||||||
1 1 1 1.0000 0.0000 1 1 1 1 a a
|
1 1 1 1.0000 0.0000 1 1 1 1 a a
|
||||||
2 5 2 2.5000 0.5000 3 2 2 3 b c
|
2 5 2 2.5000 0.5000 3 2 2 3 b c
|
||||||
3 15 3 5.0000 0.8165 7 4 4 6 C E
|
3 15 3 5.0000 0.8165 7 4 4 6 C E
|
||||||
@@ -204,3 +204,44 @@ select max(t2.a1) from t1 left outer join t2 on t1.a2=t2.a1 and 1=0 where t2.a1=
|
|||||||
max(t2.a1)
|
max(t2.a1)
|
||||||
NULL
|
NULL
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1;
|
||||||
|
count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
0 NULL NULL NULL NULL NULL -1 0
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
insert into t1 values (1,null);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
1 0 NULL NULL NULL NULL NULL -1 0
|
||||||
|
insert into t1 values (1,null);
|
||||||
|
insert into t1 values (2,null);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
1 0 NULL NULL NULL NULL NULL 0 0
|
||||||
|
2 0 NULL NULL NULL NULL NULL 0 0
|
||||||
|
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
1 0 NULL NULL NULL NULL NULL -1 0
|
||||||
|
2 0 NULL NULL NULL NULL NULL -1 0
|
||||||
|
insert into t1 values (2,1);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
1 0 NULL NULL NULL NULL NULL 0 0
|
||||||
|
2 1 1 1.0000 0.0000 1 1 0 1
|
||||||
|
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
1 0 NULL NULL NULL NULL NULL -1 0
|
||||||
|
2 1 1 1.0000 0.0000 1 1 1 1
|
||||||
|
insert into t1 values (3,1);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
1 0 NULL NULL NULL NULL NULL 0 0
|
||||||
|
2 1 1 1.0000 0.0000 1 1 0 1
|
||||||
|
3 1 1 1.0000 0.0000 1 1 1 1
|
||||||
|
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
|
||||||
|
1 0 NULL NULL NULL NULL NULL -1 0
|
||||||
|
2 1 1 1.0000 0.0000 1 1 1 1
|
||||||
|
3 1 1 1.0000 0.0000 1 1 1 1
|
||||||
|
drop table t1;
|
||||||
|
@@ -126,3 +126,24 @@ select max(t1.a2) from t1 left outer join t2 on t1.a1=10 where t1.a1=20;
|
|||||||
select max(t1.a2) from t1 left outer join t2 on t1.a1=10 where t1.a1=10;
|
select max(t1.a2) from t1 left outer join t2 on t1.a1=10 where t1.a1=10;
|
||||||
select max(t2.a1) from t1 left outer join t2 on t1.a2=t2.a1 and 1=0 where t2.a1='AAA';
|
select max(t2.a1) from t1 left outer join t2 on t1.a2=t2.a1 and 1=0 where t2.a1='AAA';
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test of group function and NULL values
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1;
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
insert into t1 values (1,null);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
insert into t1 values (1,null);
|
||||||
|
insert into t1 values (2,null);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
insert into t1 values (2,1);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
insert into t1 values (3,1);
|
||||||
|
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
|
||||||
|
drop table t1;
|
||||||
|
@@ -224,7 +224,7 @@ then
|
|||||||
if test -n "$open_files"
|
if test -n "$open_files"
|
||||||
then
|
then
|
||||||
ulimit -n $open_files
|
ulimit -n $open_files
|
||||||
args="open-files-limit=$open_files $args"
|
args="--open-files-limit=$open_files $args"
|
||||||
fi
|
fi
|
||||||
if test -n "$core_file_size"
|
if test -n "$core_file_size"
|
||||||
then
|
then
|
||||||
|
@@ -242,6 +242,10 @@ convert_error_code_to_mysql(
|
|||||||
|
|
||||||
return(HA_ERR_CANNOT_ADD_FOREIGN);
|
return(HA_ERR_CANNOT_ADD_FOREIGN);
|
||||||
|
|
||||||
|
} else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
|
||||||
|
|
||||||
|
return(HA_WRONG_CREATE_OPTION);
|
||||||
|
|
||||||
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
|
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
|
||||||
|
|
||||||
return(HA_ERR_CRASHED);
|
return(HA_ERR_CRASHED);
|
||||||
@@ -3049,6 +3053,9 @@ ha_innobase::create(
|
|||||||
|
|
||||||
trx = trx_allocate_for_mysql();
|
trx = trx_allocate_for_mysql();
|
||||||
|
|
||||||
|
trx->mysql_thd = thd;
|
||||||
|
trx->mysql_query_str = &((*thd).query);
|
||||||
|
|
||||||
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
|
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
|
||||||
trx->check_foreigns = FALSE;
|
trx->check_foreigns = FALSE;
|
||||||
}
|
}
|
||||||
@@ -3231,6 +3238,9 @@ ha_innobase::delete_table(
|
|||||||
|
|
||||||
trx = trx_allocate_for_mysql();
|
trx = trx_allocate_for_mysql();
|
||||||
|
|
||||||
|
trx->mysql_thd = current_thd;
|
||||||
|
trx->mysql_query_str = &((*current_thd).query);
|
||||||
|
|
||||||
name_len = strlen(name);
|
name_len = strlen(name);
|
||||||
|
|
||||||
assert(name_len < 1000);
|
assert(name_len < 1000);
|
||||||
@@ -3309,6 +3319,8 @@ innobase_drop_database(
|
|||||||
casedn_str(namebuf);
|
casedn_str(namebuf);
|
||||||
#endif
|
#endif
|
||||||
trx = trx_allocate_for_mysql();
|
trx = trx_allocate_for_mysql();
|
||||||
|
trx->mysql_thd = current_thd;
|
||||||
|
trx->mysql_query_str = &((*current_thd).query);
|
||||||
|
|
||||||
error = row_drop_database_for_mysql(namebuf, trx);
|
error = row_drop_database_for_mysql(namebuf, trx);
|
||||||
|
|
||||||
@@ -3368,6 +3380,8 @@ ha_innobase::rename_table(
|
|||||||
}
|
}
|
||||||
|
|
||||||
trx = trx_allocate_for_mysql();
|
trx = trx_allocate_for_mysql();
|
||||||
|
trx->mysql_thd = current_thd;
|
||||||
|
trx->mysql_query_str = &((*current_thd).query);
|
||||||
|
|
||||||
name_len1 = strlen(from);
|
name_len1 = strlen(from);
|
||||||
name_len2 = strlen(to);
|
name_len2 = strlen(to);
|
||||||
|
@@ -175,12 +175,14 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
|
|||||||
|
|
||||||
void Item_sum_sum::reset()
|
void Item_sum_sum::reset()
|
||||||
{
|
{
|
||||||
null_value=0; sum=0.0; Item_sum_sum::add();
|
null_value=1; sum=0.0; Item_sum_sum::add();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item_sum_sum::add()
|
bool Item_sum_sum::add()
|
||||||
{
|
{
|
||||||
sum+=args[0]->val();
|
sum+=args[0]->val();
|
||||||
|
if (!args[0]->null_value)
|
||||||
|
null_value= 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,7 +568,9 @@ void Item_sum_sum::reset_field()
|
|||||||
{
|
{
|
||||||
double nr=args[0]->val(); // Nulls also return 0
|
double nr=args[0]->val(); // Nulls also return 0
|
||||||
float8store(result_field->ptr,nr);
|
float8store(result_field->ptr,nr);
|
||||||
null_value=0;
|
if (args[0]->null_value)
|
||||||
|
result_field->set_null();
|
||||||
|
else
|
||||||
result_field->set_notnull();
|
result_field->set_notnull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,7 +627,10 @@ void Item_sum_sum::update_field(int offset)
|
|||||||
float8get(old_nr,res+offset);
|
float8get(old_nr,res+offset);
|
||||||
nr=args[0]->val();
|
nr=args[0]->val();
|
||||||
if (!args[0]->null_value)
|
if (!args[0]->null_value)
|
||||||
|
{
|
||||||
old_nr+=nr;
|
old_nr+=nr;
|
||||||
|
result_field->set_notnull();
|
||||||
|
}
|
||||||
float8store(res,old_nr);
|
float8store(res,old_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -92,9 +92,6 @@ public:
|
|||||||
|
|
||||||
class Item_sum_int :public Item_sum_num
|
class Item_sum_int :public Item_sum_num
|
||||||
{
|
{
|
||||||
void fix_length_and_dec()
|
|
||||||
{ decimals=0; max_length=21; maybe_null=null_value=0; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
|
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
|
||||||
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
|
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
|
||||||
@@ -102,6 +99,8 @@ public:
|
|||||||
String *val_str(String*str);
|
String *val_str(String*str);
|
||||||
enum Item_result result_type () const { return INT_RESULT; }
|
enum Item_result result_type () const { return INT_RESULT; }
|
||||||
unsigned int size_of() { return sizeof(*this);}
|
unsigned int size_of() { return sizeof(*this);}
|
||||||
|
void fix_length_and_dec()
|
||||||
|
{ decimals=0; max_length=21; maybe_null=null_value=0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -118,6 +117,7 @@ class Item_sum_sum :public Item_sum_num
|
|||||||
double val();
|
double val();
|
||||||
void reset_field();
|
void reset_field();
|
||||||
void update_field(int offset);
|
void update_field(int offset);
|
||||||
|
void no_rows_in_result() {}
|
||||||
const char *func_name() const { return "sum"; }
|
const char *func_name() const { return "sum"; }
|
||||||
unsigned int size_of() { return sizeof(*this);}
|
unsigned int size_of() { return sizeof(*this);}
|
||||||
};
|
};
|
||||||
@@ -361,6 +361,8 @@ class Item_sum_bit :public Item_sum_int
|
|||||||
longlong val_int();
|
longlong val_int();
|
||||||
void reset_field();
|
void reset_field();
|
||||||
unsigned int size_of() { return sizeof(*this);}
|
unsigned int size_of() { return sizeof(*this);}
|
||||||
|
void fix_length_and_dec()
|
||||||
|
{ decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -921,6 +921,8 @@ void clean_up(bool print_message)
|
|||||||
free_max_user_conn();
|
free_max_user_conn();
|
||||||
end_slave_list();
|
end_slave_list();
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
|
if (ssl_acceptor_fd)
|
||||||
|
my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
free_des_key_file();
|
free_des_key_file();
|
||||||
#endif /* HAVE_OPENSSL */
|
#endif /* HAVE_OPENSSL */
|
||||||
#ifdef USE_REGEX
|
#ifdef USE_REGEX
|
||||||
@@ -3562,7 +3564,7 @@ relay logs",
|
|||||||
{"skip-stack-trace", OPT_SKIP_STACK_TRACE,
|
{"skip-stack-trace", OPT_SKIP_STACK_TRACE,
|
||||||
"Don't print a stack trace on failure", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
|
"Don't print a stack trace on failure", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
|
||||||
0, 0, 0, 0},
|
0, 0, 0, 0},
|
||||||
{"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables",
|
{"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. Depricated option. Use --skip-symbolic-links instead",
|
||||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"skip-thread-priority", OPT_SKIP_PRIOR,
|
{"skip-thread-priority", OPT_SKIP_PRIOR,
|
||||||
"Don't give threads different priorities.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
|
"Don't give threads different priorities.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
|
||||||
@@ -3606,11 +3608,12 @@ replicating a LOAD DATA INFILE command",
|
|||||||
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running",
|
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running",
|
||||||
(gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
|
(gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
|
||||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
#ifdef USE_SYMDIR
|
{"use-symbolic-links", 's', "Enable symbolic link support. Depricated option; Use --symbolic-links instead",
|
||||||
{"use-symbolic-links", 's', "Enable symbolic link support",
|
(gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
|
||||||
|
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
|
||||||
|
{"--symbolic-links", 's', "Enable symbolic link support",
|
||||||
(gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
|
(gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
|
||||||
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
|
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
|
||||||
#endif
|
|
||||||
{"user", 'u', "Run mysqld daemon as user", 0, 0, 0, GET_STR, REQUIRED_ARG,
|
{"user", 'u', "Run mysqld daemon as user", 0, 0, 0, GET_STR, REQUIRED_ARG,
|
||||||
0, 0, 0, 0, 0, 0},
|
0, 0, 0, 0, 0, 0},
|
||||||
{"version", 'V', "Output version information and exit", 0, 0, 0, GET_NO_ARG,
|
{"version", 'V', "Output version information and exit", 0, 0, 0, GET_NO_ARG,
|
||||||
@@ -4424,9 +4427,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||||||
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
|
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
|
||||||
myisam_concurrent_insert=0;
|
myisam_concurrent_insert=0;
|
||||||
myisam_recover_options= HA_RECOVER_NONE;
|
myisam_recover_options= HA_RECOVER_NONE;
|
||||||
my_disable_symlinks=1;
|
|
||||||
my_use_symdir=0;
|
my_use_symdir=0;
|
||||||
have_symlink=SHOW_OPTION_DISABLED;
|
|
||||||
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
|
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
query_cache_size=0;
|
query_cache_size=0;
|
||||||
@@ -4473,9 +4474,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||||||
test_flags|=TEST_NO_STACKTRACE;
|
test_flags|=TEST_NO_STACKTRACE;
|
||||||
break;
|
break;
|
||||||
case (int) OPT_SKIP_SYMLINKS:
|
case (int) OPT_SKIP_SYMLINKS:
|
||||||
my_disable_symlinks=1;
|
|
||||||
my_use_symdir=0;
|
my_use_symdir=0;
|
||||||
have_symlink=SHOW_OPTION_DISABLED;
|
|
||||||
break;
|
break;
|
||||||
case (int) OPT_BIND_ADDRESS:
|
case (int) OPT_BIND_ADDRESS:
|
||||||
if (argument && isdigit(argument[0]))
|
if (argument && isdigit(argument[0]))
|
||||||
|
@@ -47,13 +47,6 @@
|
|||||||
can't normally do this the client should have a bigger max_allowed_packet.
|
can't normally do this the client should have a bigger max_allowed_packet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef MYSQL_SERVER
|
|
||||||
#define USE_QUERY_CACHE
|
|
||||||
extern uint test_flags;
|
|
||||||
extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__WIN__) || !defined(MYSQL_SERVER)
|
#if defined(__WIN__) || !defined(MYSQL_SERVER)
|
||||||
/* The following is because alarms doesn't work on windows. */
|
/* The following is because alarms doesn't work on windows. */
|
||||||
#define NO_ALARM
|
#define NO_ALARM
|
||||||
@@ -62,15 +55,22 @@ extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
|||||||
#ifndef NO_ALARM
|
#ifndef NO_ALARM
|
||||||
#include "my_pthread.h"
|
#include "my_pthread.h"
|
||||||
void sql_print_error(const char *format,...);
|
void sql_print_error(const char *format,...);
|
||||||
|
#else
|
||||||
|
#define DONT_USE_THR_ALARM
|
||||||
|
#endif /* NO_ALARM */
|
||||||
|
|
||||||
|
#include "thr_alarm.h"
|
||||||
|
|
||||||
|
#ifdef MYSQL_SERVER
|
||||||
|
#define USE_QUERY_CACHE
|
||||||
|
extern uint test_flags;
|
||||||
|
extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
||||||
extern ulong bytes_sent, bytes_received;
|
extern ulong bytes_sent, bytes_received;
|
||||||
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
|
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
|
||||||
#else
|
#else
|
||||||
#undef statistic_add
|
#undef statistic_add
|
||||||
#define statistic_add(A,B,C)
|
#define statistic_add(A,B,C)
|
||||||
#define DONT_USE_THR_ALARM
|
#endif
|
||||||
#endif /* NO_ALARM */
|
|
||||||
|
|
||||||
#include "thr_alarm.h"
|
|
||||||
|
|
||||||
#define TEST_BLOCKING 8
|
#define TEST_BLOCKING 8
|
||||||
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
|
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
|
||||||
|
@@ -542,19 +542,19 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
|||||||
break;
|
break;
|
||||||
case SSL_TYPE_X509: /* Client should have any valid certificate. */
|
case SSL_TYPE_X509: /* Client should have any valid certificate. */
|
||||||
/*
|
/*
|
||||||
Connections with non-valid certificates are dropped already
|
We need to check for absence of SSL because without SSL
|
||||||
in sslaccept() anyway, so we do not check validity here.
|
we should reject connection.
|
||||||
*/
|
*/
|
||||||
if (SSL_get_peer_certificate(vio->ssl_))
|
if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_))
|
||||||
user_access=acl_user->access;
|
user_access=acl_user->access;
|
||||||
break;
|
break;
|
||||||
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
|
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
|
||||||
/*
|
/*
|
||||||
We do not check for absence of SSL because without SSL it does
|
We need to check for absence of SSL because without SSL
|
||||||
not pass all checks here anyway.
|
we should reject connection.
|
||||||
If cipher name is specified, we compare it to actual cipher in
|
|
||||||
use.
|
|
||||||
*/
|
*/
|
||||||
|
if (vio_type(vio) == VIO_TYPE_SSL)
|
||||||
|
{
|
||||||
if (acl_user->ssl_cipher)
|
if (acl_user->ssl_cipher)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
|
DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
|
||||||
@@ -564,6 +564,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
|||||||
user_access=acl_user->access;
|
user_access=acl_user->access;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (global_system_variables.log_warnings)
|
||||||
|
sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'",
|
||||||
|
acl_user->ssl_cipher,
|
||||||
|
SSL_get_cipher(vio->ssl_));
|
||||||
user_access=NO_ACCESS;
|
user_access=NO_ACCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -581,6 +585,9 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
|||||||
acl_user->x509_issuer, ptr));
|
acl_user->x509_issuer, ptr));
|
||||||
if (strcmp(acl_user->x509_issuer, ptr))
|
if (strcmp(acl_user->x509_issuer, ptr))
|
||||||
{
|
{
|
||||||
|
if (global_system_variables.log_warnings)
|
||||||
|
sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'",
|
||||||
|
acl_user->x509_issuer, ptr);
|
||||||
user_access=NO_ACCESS;
|
user_access=NO_ACCESS;
|
||||||
free(ptr);
|
free(ptr);
|
||||||
break;
|
break;
|
||||||
@@ -596,13 +603,19 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
|||||||
DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
|
DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
|
||||||
acl_user->x509_subject, ptr));
|
acl_user->x509_subject, ptr));
|
||||||
if (strcmp(acl_user->x509_subject,ptr))
|
if (strcmp(acl_user->x509_subject,ptr))
|
||||||
|
{
|
||||||
|
if (global_system_variables.log_warnings)
|
||||||
|
sql_print_error("X509 subject mismatch: '%s' vs '%s'",
|
||||||
|
acl_user->x509_subject, ptr);
|
||||||
user_access=NO_ACCESS;
|
user_access=NO_ACCESS;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
user_access=acl_user->access;
|
user_access=acl_user->access;
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#else /* HAVE_OPENSSL */
|
#else /* HAVE_OPENSSL */
|
||||||
user_access=acl_user->access;
|
user_access=acl_user->access;
|
||||||
#endif /* HAVE_OPENSSL */
|
#endif /* HAVE_OPENSSL */
|
||||||
|
@@ -1228,7 +1228,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
|
|||||||
case SHOW_RPL_STATUS:
|
case SHOW_RPL_STATUS:
|
||||||
net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
|
net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
|
||||||
break;
|
break;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifdef HAVE_REPLICATION
|
||||||
case SHOW_SLAVE_RUNNING:
|
case SHOW_SLAVE_RUNNING:
|
||||||
{
|
{
|
||||||
LOCK_ACTIVE_MI;
|
LOCK_ACTIVE_MI;
|
||||||
|
@@ -29,8 +29,8 @@ skip-locking
|
|||||||
set-variable = key_buffer=384M
|
set-variable = key_buffer=384M
|
||||||
set-variable = max_allowed_packet=1M
|
set-variable = max_allowed_packet=1M
|
||||||
set-variable = table_cache=512
|
set-variable = table_cache=512
|
||||||
set-variable = sort_buffer=2M
|
set-variable = sort_buffer_size=2M
|
||||||
set-variable = record_buffer=2M
|
set-variable = read_buffer_size=2M
|
||||||
set-variable = myisam_sort_buffer_size=64M
|
set-variable = myisam_sort_buffer_size=64M
|
||||||
set-variable = thread_cache=8
|
set-variable = thread_cache=8
|
||||||
# Try number of CPU's*2 for thread_concurrency
|
# Try number of CPU's*2 for thread_concurrency
|
||||||
@@ -53,7 +53,36 @@ log-bin
|
|||||||
# but will not function as a master if omitted
|
# but will not function as a master if omitted
|
||||||
server-id = 1
|
server-id = 1
|
||||||
|
|
||||||
# Replication Slave Server (comment out master section to use this)
|
# Replication Slave (comment out master section to use this)
|
||||||
|
#
|
||||||
|
# To configure this host as a replication slave, you can choose between
|
||||||
|
# two methods :
|
||||||
|
#
|
||||||
|
# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
|
||||||
|
# the syntax is:
|
||||||
|
#
|
||||||
|
# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
|
||||||
|
# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
|
||||||
|
#
|
||||||
|
# where you replace <host>, <user>, <password> by quoted strings and
|
||||||
|
# <port> by the master's port number (3306 by default).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
|
||||||
|
# MASTER_USER='joe', MASTER_PASSWORD='secret';
|
||||||
|
#
|
||||||
|
# OR
|
||||||
|
#
|
||||||
|
# 2) Set the variables below. However, in case you choose this method, then
|
||||||
|
# start replication for the first time (even unsuccessfully, for example
|
||||||
|
# if you mistyped the password in master-password and the slave fails to
|
||||||
|
# connect), the slave will create a master.info file, and any later
|
||||||
|
# change in this file to the variables' values below will be ignored and
|
||||||
|
# overridden by the content of the master.info file, unless you shutdown
|
||||||
|
# the slave server, delete master.info and restart the slaver server.
|
||||||
|
# For that reason, you may want to leave the lines below untouched
|
||||||
|
# (commented) and instead use CHANGE MASTER TO (see above)
|
||||||
#
|
#
|
||||||
# required unique id between 2 and 2^32 - 1
|
# required unique id between 2 and 2^32 - 1
|
||||||
# (and different from the master)
|
# (and different from the master)
|
||||||
@@ -113,13 +142,13 @@ no-auto-rehash
|
|||||||
|
|
||||||
[isamchk]
|
[isamchk]
|
||||||
set-variable = key_buffer=256M
|
set-variable = key_buffer=256M
|
||||||
set-variable = sort_buffer=256M
|
set-variable = sort_buffer_size=256M
|
||||||
set-variable = read_buffer=2M
|
set-variable = read_buffer=2M
|
||||||
set-variable = write_buffer=2M
|
set-variable = write_buffer=2M
|
||||||
|
|
||||||
[myisamchk]
|
[myisamchk]
|
||||||
set-variable = key_buffer=256M
|
set-variable = key_buffer=256M
|
||||||
set-variable = sort_buffer=256M
|
set-variable = sort_buffer_size=256M
|
||||||
set-variable = read_buffer=2M
|
set-variable = read_buffer=2M
|
||||||
set-variable = write_buffer=2M
|
set-variable = write_buffer=2M
|
||||||
|
|
||||||
|
@@ -29,8 +29,8 @@ skip-locking
|
|||||||
set-variable = key_buffer=256M
|
set-variable = key_buffer=256M
|
||||||
set-variable = max_allowed_packet=1M
|
set-variable = max_allowed_packet=1M
|
||||||
set-variable = table_cache=256
|
set-variable = table_cache=256
|
||||||
set-variable = sort_buffer=1M
|
set-variable = sort_buffer_size=1M
|
||||||
set-variable = record_buffer=1M
|
set-variable = read_buffer_size=1M
|
||||||
set-variable = myisam_sort_buffer_size=64M
|
set-variable = myisam_sort_buffer_size=64M
|
||||||
set-variable = thread_cache=8
|
set-variable = thread_cache=8
|
||||||
# Try number of CPU's*2 for thread_concurrency
|
# Try number of CPU's*2 for thread_concurrency
|
||||||
@@ -53,7 +53,36 @@ log-bin
|
|||||||
# but will not function as a master if omitted
|
# but will not function as a master if omitted
|
||||||
server-id = 1
|
server-id = 1
|
||||||
|
|
||||||
# Replication Slave Server (comment out master section to use this)
|
# Replication Slave (comment out master section to use this)
|
||||||
|
#
|
||||||
|
# To configure this host as a replication slave, you can choose between
|
||||||
|
# two methods :
|
||||||
|
#
|
||||||
|
# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
|
||||||
|
# the syntax is:
|
||||||
|
#
|
||||||
|
# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
|
||||||
|
# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
|
||||||
|
#
|
||||||
|
# where you replace <host>, <user>, <password> by quoted strings and
|
||||||
|
# <port> by the master's port number (3306 by default).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
|
||||||
|
# MASTER_USER='joe', MASTER_PASSWORD='secret';
|
||||||
|
#
|
||||||
|
# OR
|
||||||
|
#
|
||||||
|
# 2) Set the variables below. However, in case you choose this method, then
|
||||||
|
# start replication for the first time (even unsuccessfully, for example
|
||||||
|
# if you mistyped the password in master-password and the slave fails to
|
||||||
|
# connect), the slave will create a master.info file, and any later
|
||||||
|
# change in this file to the variables' values below will be ignored and
|
||||||
|
# overridden by the content of the master.info file, unless you shutdown
|
||||||
|
# the slave server, delete master.info and restart the slaver server.
|
||||||
|
# For that reason, you may want to leave the lines below untouched
|
||||||
|
# (commented) and instead use CHANGE MASTER TO (see above)
|
||||||
#
|
#
|
||||||
# required unique id between 2 and 2^32 - 1
|
# required unique id between 2 and 2^32 - 1
|
||||||
# (and different from the master)
|
# (and different from the master)
|
||||||
@@ -113,13 +142,13 @@ no-auto-rehash
|
|||||||
|
|
||||||
[isamchk]
|
[isamchk]
|
||||||
set-variable = key_buffer=128M
|
set-variable = key_buffer=128M
|
||||||
set-variable = sort_buffer=128M
|
set-variable = sort_buffer_size=128M
|
||||||
set-variable = read_buffer=2M
|
set-variable = read_buffer=2M
|
||||||
set-variable = write_buffer=2M
|
set-variable = write_buffer=2M
|
||||||
|
|
||||||
[myisamchk]
|
[myisamchk]
|
||||||
set-variable = key_buffer=128M
|
set-variable = key_buffer=128M
|
||||||
set-variable = sort_buffer=128M
|
set-variable = sort_buffer_size=128M
|
||||||
set-variable = read_buffer=2M
|
set-variable = read_buffer=2M
|
||||||
set-variable = write_buffer=2M
|
set-variable = write_buffer=2M
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ skip-locking
|
|||||||
set-variable = key_buffer=16M
|
set-variable = key_buffer=16M
|
||||||
set-variable = max_allowed_packet=1M
|
set-variable = max_allowed_packet=1M
|
||||||
set-variable = table_cache=64
|
set-variable = table_cache=64
|
||||||
set-variable = sort_buffer=512K
|
set-variable = sort_buffer_size=512K
|
||||||
set-variable = net_buffer_length=8K
|
set-variable = net_buffer_length=8K
|
||||||
set-variable = myisam_sort_buffer_size=8M
|
set-variable = myisam_sort_buffer_size=8M
|
||||||
|
|
||||||
@@ -51,7 +51,36 @@ log-bin
|
|||||||
# but will not function as a master if omitted
|
# but will not function as a master if omitted
|
||||||
server-id = 1
|
server-id = 1
|
||||||
|
|
||||||
# Replication Slave Server (comment out master section to use this)
|
# Replication Slave (comment out master section to use this)
|
||||||
|
#
|
||||||
|
# To configure this host as a replication slave, you can choose between
|
||||||
|
# two methods :
|
||||||
|
#
|
||||||
|
# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
|
||||||
|
# the syntax is:
|
||||||
|
#
|
||||||
|
# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
|
||||||
|
# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
|
||||||
|
#
|
||||||
|
# where you replace <host>, <user>, <password> by quoted strings and
|
||||||
|
# <port> by the master's port number (3306 by default).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
|
||||||
|
# MASTER_USER='joe', MASTER_PASSWORD='secret';
|
||||||
|
#
|
||||||
|
# OR
|
||||||
|
#
|
||||||
|
# 2) Set the variables below. However, in case you choose this method, then
|
||||||
|
# start replication for the first time (even unsuccessfully, for example
|
||||||
|
# if you mistyped the password in master-password and the slave fails to
|
||||||
|
# connect), the slave will create a master.info file, and any later
|
||||||
|
# change in this file to the variables' values below will be ignored and
|
||||||
|
# overridden by the content of the master.info file, unless you shutdown
|
||||||
|
# the slave server, delete master.info and restart the slaver server.
|
||||||
|
# For that reason, you may want to leave the lines below untouched
|
||||||
|
# (commented) and instead use CHANGE MASTER TO (see above)
|
||||||
#
|
#
|
||||||
# required unique id between 2 and 2^32 - 1
|
# required unique id between 2 and 2^32 - 1
|
||||||
# (and different from the master)
|
# (and different from the master)
|
||||||
@@ -111,13 +140,13 @@ no-auto-rehash
|
|||||||
|
|
||||||
[isamchk]
|
[isamchk]
|
||||||
set-variable = key_buffer=20M
|
set-variable = key_buffer=20M
|
||||||
set-variable = sort_buffer=20M
|
set-variable = sort_buffer_size=20M
|
||||||
set-variable = read_buffer=2M
|
set-variable = read_buffer=2M
|
||||||
set-variable = write_buffer=2M
|
set-variable = write_buffer=2M
|
||||||
|
|
||||||
[myisamchk]
|
[myisamchk]
|
||||||
set-variable = key_buffer=20M
|
set-variable = key_buffer=20M
|
||||||
set-variable = sort_buffer=20M
|
set-variable = sort_buffer_size=20M
|
||||||
set-variable = read_buffer=2M
|
set-variable = read_buffer=2M
|
||||||
set-variable = write_buffer=2M
|
set-variable = write_buffer=2M
|
||||||
|
|
||||||
|
@@ -29,10 +29,18 @@ socket = @MYSQL_UNIX_ADDR@
|
|||||||
skip-locking
|
skip-locking
|
||||||
set-variable = key_buffer=16K
|
set-variable = key_buffer=16K
|
||||||
set-variable = max_allowed_packet=1M
|
set-variable = max_allowed_packet=1M
|
||||||
set-variable = thread_stack=64K
|
|
||||||
set-variable = table_cache=4
|
set-variable = table_cache=4
|
||||||
set-variable = sort_buffer=64K
|
set-variable = sort_buffer_size=64K
|
||||||
set-variable = net_buffer_length=2K
|
set-variable = net_buffer_length=2K
|
||||||
|
set-variable = thread_stack=64K
|
||||||
|
|
||||||
|
# Don't listen on a TCP/IP port at all. This can be a security enhancement,
|
||||||
|
# if all processes that need to connect to mysqld run on the same host.
|
||||||
|
# All interaction with mysqld must be made via Unix sockets or named pipes.
|
||||||
|
# Note that using this option without enabling named pipes on Windows
|
||||||
|
# (via the "pipe" option) will render mysqld useless!
|
||||||
|
#
|
||||||
|
#skip-networking
|
||||||
server-id = 1
|
server-id = 1
|
||||||
|
|
||||||
# Uncomment the following if you want to log updates
|
# Uncomment the following if you want to log updates
|
||||||
@@ -67,11 +75,11 @@ no-auto-rehash
|
|||||||
|
|
||||||
[isamchk]
|
[isamchk]
|
||||||
set-variable = key_buffer=8M
|
set-variable = key_buffer=8M
|
||||||
set-variable = sort_buffer=8M
|
set-variable = sort_buffer_size=8M
|
||||||
|
|
||||||
[myisamchk]
|
[myisamchk]
|
||||||
set-variable = key_buffer=8M
|
set-variable = key_buffer=8M
|
||||||
set-variable = sort_buffer=8M
|
set-variable = sort_buffer_size=8M
|
||||||
|
|
||||||
[mysqlhotcopy]
|
[mysqlhotcopy]
|
||||||
interactive-timeout
|
interactive-timeout
|
||||||
|
@@ -281,7 +281,8 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
|
|||||||
SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
|
SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
|
||||||
SSL_set_fd(vio->ssl_,vio->sd);
|
SSL_set_fd(vio->ssl_,vio->sd);
|
||||||
SSL_set_accept_state(vio->ssl_);
|
SSL_set_accept_state(vio->ssl_);
|
||||||
if (SSL_do_handshake(vio->ssl_) < 1)
|
if (SSL_do_handshake(vio->ssl_) < 1 ||
|
||||||
|
SSL_get_verify_result(vio->ssl_) != X509_V_OK)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("SSL_do_handshake failure"));
|
DBUG_PRINT("error", ("SSL_do_handshake failure"));
|
||||||
report_errors();
|
report_errors();
|
||||||
@@ -354,7 +355,8 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
|
|||||||
SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
|
SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
|
||||||
SSL_set_fd (vio->ssl_, vio->sd);
|
SSL_set_fd (vio->ssl_, vio->sd);
|
||||||
SSL_set_connect_state(vio->ssl_);
|
SSL_set_connect_state(vio->ssl_);
|
||||||
if (SSL_do_handshake(vio->ssl_) < 1)
|
if (SSL_do_handshake(vio->ssl_) < 1 ||
|
||||||
|
SSL_get_verify_result(vio->ssl_) != X509_V_OK)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("SSL_do_handshake failure"));
|
DBUG_PRINT("error", ("SSL_do_handshake failure"));
|
||||||
report_errors();
|
report_errors();
|
||||||
|
Reference in New Issue
Block a user