diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-12-14 14:34:32 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2015-12-14 22:10:37 +0200 |
commit | 99404c3437b35b5ee51578c2ea74209ccb9ba890 (patch) | |
tree | 7dc58eefe89b0d799589d2ca3d95a452e6e69916 /storage | |
parent | 0db50be89349761d5677441f2d60ab52c23947f0 (diff) | |
download | mariadb-git-99404c3437b35b5ee51578c2ea74209ccb9ba890.tar.gz |
MDEV-9276: MySQL Bug #78754: FK definitions missing from SHOW CREATE TABLE in "innodb_read_only" mode
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 110 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 103 | ||||
-rw-r--r-- | storage/innobase/include/dict0dict.h | 13 | ||||
-rw-r--r-- | storage/innobase/include/ut0ut.h | 16 | ||||
-rw-r--r-- | storage/innobase/row/row0ins.cc | 22 | ||||
-rw-r--r-- | storage/innobase/ut/ut0ut.cc | 30 | ||||
-rw-r--r-- | storage/xtradb/dict/dict0dict.cc | 110 | ||||
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 103 | ||||
-rw-r--r-- | storage/xtradb/include/dict0dict.h | 13 | ||||
-rw-r--r-- | storage/xtradb/include/ut0ut.h | 16 | ||||
-rw-r--r-- | storage/xtradb/row/row0ins.cc | 22 | ||||
-rw-r--r-- | storage/xtradb/ut/ut0ut.cc | 30 |
12 files changed, 332 insertions, 256 deletions
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 09893d2d645..b5e97a2c3f4 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2,6 +2,7 @@ Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -28,6 +29,7 @@ Created 1/8/1996 Heikki Tuuri #include "fts0fts.h" #include "fil0fil.h" #include <algorithm> +#include <string> #ifdef UNIV_NONINL #include "dict0dict.ic" @@ -3468,11 +3470,13 @@ dict_foreign_error_report( dict_foreign_t* fk, /*!< in: foreign key constraint */ const char* msg) /*!< in: the error message */ { + std::string fk_str; mutex_enter(&dict_foreign_err_mutex); dict_foreign_error_report_low(file, fk->foreign_table_name); fputs(msg, file); fputs(" Constraint:\n", file); - dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE); + fk_str = dict_print_info_on_foreign_key_in_create_format(NULL, fk, TRUE); + fputs(fk_str.c_str(), file); putc('\n', file); if (fk->foreign_index) { fputs("The index in the foreign key in table is ", file); @@ -5861,16 +5865,16 @@ dict_field_print_low( Outputs info on a foreign key of a table in a format suitable for CREATE TABLE. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ dict_foreign_t* foreign, /*!< in: foreign key constraint */ ibool add_newline) /*!< in: whether to add a newline */ { const char* stripped_id; ulint i; + std::string str; if (strchr(foreign->id, '/')) { /* Strip the preceding database name from the constraint id */ @@ -5880,96 +5884,99 @@ dict_print_info_on_foreign_key_in_create_format( stripped_id = foreign->id; } - putc(',', file); + str.append(","); if (add_newline) { /* SHOW CREATE TABLE wants constraints each printed nicely on its own line, while error messages want no newlines inserted. */ - fputs("\n ", file); + str.append("\n "); } - fputs(" CONSTRAINT ", file); - ut_print_name(file, trx, FALSE, stripped_id); - fputs(" FOREIGN KEY (", file); + str.append(" CONSTRAINT "); + + str.append(ut_get_name(trx, FALSE, stripped_id)); + str.append(" FOREIGN KEY ("); for (i = 0;;) { - ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]); + str.append(ut_get_name(trx, FALSE, foreign->foreign_col_names[i])); if (++i < foreign->n_fields) { - fputs(", ", file); + str.append(", "); } else { break; } } - fputs(") REFERENCES ", file); + str.append(") REFERENCES "); if (dict_tables_have_same_db(foreign->foreign_table_name_lookup, foreign->referenced_table_name_lookup)) { /* Do not print the database name of the referenced table */ - ut_print_name(file, trx, TRUE, + str.append(ut_get_name(trx, TRUE, dict_remove_db_name( - foreign->referenced_table_name)); + foreign->referenced_table_name))); } else { - ut_print_name(file, trx, TRUE, - foreign->referenced_table_name); + str.append(ut_get_name(trx, TRUE, + foreign->referenced_table_name)); } - putc(' ', file); - putc('(', file); + str.append(" ("); for (i = 0;;) { - ut_print_name(file, trx, FALSE, - foreign->referenced_col_names[i]); + str.append(ut_get_name(trx, FALSE, + foreign->referenced_col_names[i])); + if (++i < foreign->n_fields) { - fputs(", ", file); + str.append(", "); } else { break; } } - putc(')', file); + str.append(")"); if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) { - fputs(" ON DELETE CASCADE", file); + str.append(" ON DELETE CASCADE"); } if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) { - fputs(" ON DELETE SET NULL", file); + str.append(" ON DELETE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) { - fputs(" ON DELETE NO ACTION", file); + str.append(" ON DELETE NO ACTION"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { - fputs(" ON UPDATE CASCADE", file); + str.append(" ON UPDATE CASCADE"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { - fputs(" ON UPDATE SET NULL", file); + str.append(" ON UPDATE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) { - fputs(" ON UPDATE NO ACTION", file); + str.append(" ON UPDATE NO ACTION"); } + + return str; } /**********************************************************************//** Outputs info on foreign keys of a table. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_keys( /*============================*/ ibool create_table_format, /*!< in: if TRUE then print in a format suitable to be inserted into a CREATE TABLE, otherwise in the format of SHOW TABLE STATUS */ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ dict_table_t* table) /*!< in: table */ { dict_foreign_t* foreign; + std::string str; mutex_enter(&(dict_sys->mutex)); @@ -5980,64 +5987,67 @@ dict_print_info_on_foreign_keys( foreign = *it; if (create_table_format) { - dict_print_info_on_foreign_key_in_create_format( - file, trx, foreign, TRUE); + str.append( + dict_print_info_on_foreign_key_in_create_format( + trx, foreign, TRUE)); } else { ulint i; - fputs("; (", file); + str.append("; ("); for (i = 0; i < foreign->n_fields; i++) { if (i) { - putc(' ', file); + str.append(" "); } - ut_print_name(file, trx, FALSE, - foreign->foreign_col_names[i]); + str.append(ut_get_name(trx, FALSE, + foreign->foreign_col_names[i])); } - fputs(") REFER ", file); - ut_print_name(file, trx, TRUE, - foreign->referenced_table_name); - putc('(', file); + str.append(") REFER "); + str.append(ut_get_name(trx, TRUE, + foreign->referenced_table_name)); + str.append(")"); for (i = 0; i < foreign->n_fields; i++) { if (i) { - putc(' ', file); + str.append(" "); } - ut_print_name( - file, trx, FALSE, - foreign->referenced_col_names[i]); + str.append(ut_get_name( + trx, FALSE, + foreign->referenced_col_names[i])); } - putc(')', file); + str.append(")"); if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) { - fputs(" ON DELETE CASCADE", file); + str.append(" ON DELETE CASCADE"); } if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) { - fputs(" ON DELETE SET NULL", file); + str.append(" ON DELETE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) { - fputs(" ON DELETE NO ACTION", file); + str.append(" ON DELETE NO ACTION"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { - fputs(" ON UPDATE CASCADE", file); + str.append(" ON UPDATE CASCADE"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { - fputs(" ON UPDATE SET NULL", file); + str.append(" ON UPDATE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) { - fputs(" ON UPDATE NO ACTION", file); + str.append(" ON UPDATE NO ACTION"); } } } mutex_exit(&(dict_sys->mutex)); + + return str; } /********************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f6c2a08ee38..fde5683653b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -112,6 +112,9 @@ this program; if not, write to the Free Software Foundation, Inc., #include "ha_innodb.h" #include "i_s.h" +#include <string> +#include <sstream> + # ifndef MYSQL_PLUGIN_IMPORT # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ @@ -11949,8 +11952,9 @@ ha_innobase::update_table_comment( const char* comment)/*!< in: table comment defined by user */ { uint length = (uint) strlen(comment); - char* str; + char* str=0; long flen; + std::string fk_str; /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -11968,50 +11972,40 @@ ha_innobase::update_table_comment( possible adaptive hash latch to avoid deadlocks of threads */ trx_search_latch_release_if_reserved(prebuilt->trx); - str = NULL; - - /* output the data to a temporary file */ - if (!srv_read_only_mode) { - - mutex_enter(&srv_dict_tmpfile_mutex); +#define SSTR( x ) reinterpret_cast< std::ostringstream & >( \ + ( std::ostringstream() << std::dec << x ) ).str() - rewind(srv_dict_tmpfile); + fk_str.append("InnoDB free: "); + fk_str.append(SSTR(fsp_get_available_space_in_free_extents( + prebuilt->table->space))); - fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB", - fsp_get_available_space_in_free_extents( - prebuilt->table->space)); + fk_str.append(dict_print_info_on_foreign_keys( + FALSE, prebuilt->trx, + prebuilt->table)); - dict_print_info_on_foreign_keys( - FALSE, srv_dict_tmpfile, prebuilt->trx, - prebuilt->table); + flen = fk_str.length(); - flen = ftell(srv_dict_tmpfile); - - if (flen < 0) { - flen = 0; - } else if (length + flen + 3 > 64000) { - flen = 64000 - 3 - length; - } + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { + flen = 64000 - 3 - length; + } - /* allocate buffer for the full string, and - read the contents of the temporary file */ + /* allocate buffer for the full string */ - str = (char*) my_malloc(length + flen + 3, MYF(0)); + str = (char*) my_malloc(length + flen + 3, MYF(0)); - if (str) { - char* pos = str + length; - if (length) { - memcpy(str, comment, length); - *pos++ = ';'; - *pos++ = ' '; - } - rewind(srv_dict_tmpfile); - flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile); - pos[flen] = 0; + if (str) { + char* pos = str + length; + if (length) { + memcpy(str, comment, length); + *pos++ = ';'; + *pos++ = ' '; } - mutex_exit(&srv_dict_tmpfile_mutex); + memcpy(pos, fk_str.c_str(), flen); + pos[flen] = 0; } prebuilt->trx->op_info = (char*)""; @@ -12029,8 +12023,7 @@ char* ha_innobase::get_foreign_key_create_info(void) /*==========================================*/ { - long flen; - char* str = 0; + char* fk_str = 0; ut_a(prebuilt != NULL); @@ -12048,38 +12041,22 @@ ha_innobase::get_foreign_key_create_info(void) trx_search_latch_release_if_reserved(prebuilt->trx); - if (!srv_read_only_mode) { - mutex_enter(&srv_dict_tmpfile_mutex); - rewind(srv_dict_tmpfile); - - /* Output the data to a temporary file */ - dict_print_info_on_foreign_keys( - TRUE, srv_dict_tmpfile, prebuilt->trx, + /* Output the data to a temporary file */ + std::string str = dict_print_info_on_foreign_keys( + TRUE, prebuilt->trx, prebuilt->table); - prebuilt->trx->op_info = (char*)""; - - flen = ftell(srv_dict_tmpfile); - - if (flen < 0) { - flen = 0; - } - - /* Allocate buffer for the string, and - read the contents of the temporary file */ - - str = (char*) my_malloc(flen + 1, MYF(0)); + prebuilt->trx->op_info = (char*)""; - if (str) { - rewind(srv_dict_tmpfile); - flen = (uint) fread(str, 1, flen, srv_dict_tmpfile); - str[flen] = 0; - } + /* Allocate buffer for the string */ + fk_str = (char*) my_malloc(str.length() + 1, MYF(0)); - mutex_exit(&srv_dict_tmpfile_mutex); + if (fk_str) { + memcpy(fk_str, str.c_str(), str.length()); + fk_str[str.length()]='\0'; } - return(str); + return(fk_str); } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 5266cf7d245..4332867fa15 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -2,6 +2,7 @@ Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -625,29 +626,25 @@ dict_table_print( /**********************************************************************//** Outputs info on foreign keys of a table. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_keys( /*============================*/ ibool create_table_format, /*!< in: if TRUE then print in a format suitable to be inserted into a CREATE TABLE, otherwise in the format of SHOW TABLE STATUS */ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ - dict_table_t* table) /*!< in: table */ - __attribute__((nonnull)); + dict_table_t* table); /*!< in: table */ /**********************************************************************//** Outputs info on a foreign key of a table in a format suitable for CREATE TABLE. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ dict_foreign_t* foreign, /*!< in: foreign key constraint */ - ibool add_newline) /*!< in: whether to add a newline */ - __attribute__((nonnull(1,3))); + ibool add_newline); /*!< in: whether to add a newline */ /********************************************************************//** Displays the names of the index and the table. */ UNIV_INTERN diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 939ccee6e3e..32a4d971d94 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -45,6 +45,8 @@ Created 1/20/1994 Heikki Tuuri #include <stdarg.h> /* for va_list */ +#include <string> + /** Index name prefix in fast index creation */ #define TEMP_INDEX_PREFIX '\377' /** Index name prefix in fast index creation, as a string constant */ @@ -395,7 +397,19 @@ ut_print_namel( FALSE=print other identifier */ const char* name, /*!< in: name to print */ ulint namelen);/*!< in: length of name */ - +/**********************************************************************//** +Outputs a fixed-length string, quoted as an SQL identifier. +If the string contains a slash '/', the string will be +output as two identifiers separated by a period (.), +as in SQL database_name.identifier. */ +UNIV_INTERN +std::string +ut_get_name( +/*=========*/ + const trx_t* trx, /*!< in: transaction (NULL=no quotes) */ + ibool table_id,/*!< in: TRUE=print a table name, + FALSE=print other identifier */ + const char* name); /*!< in: name to print */ /**********************************************************************//** Formats a table or index name, quoted as an SQL identifier. If the name contains a slash '/', the result will contain two identifiers separated by diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 9f22889c5fb..e75a039ddc6 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -730,10 +730,12 @@ row_ins_set_detailed( rewind(srv_misc_tmpfile); if (os_file_set_eof(srv_misc_tmpfile)) { + std::string fk_str; ut_print_name(srv_misc_tmpfile, trx, TRUE, foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format( - srv_misc_tmpfile, trx, foreign, FALSE); + fk_str = dict_print_info_on_foreign_key_in_create_format( + trx, foreign, FALSE); + fputs(fk_str.c_str(), srv_misc_tmpfile); trx_set_detailed_error_from_file(trx, srv_misc_tmpfile); } else { trx_set_detailed_error(trx, "temp file operation failed"); @@ -798,6 +800,8 @@ row_ins_foreign_report_err( const dtuple_t* entry) /*!< in: index entry in the parent table */ { + std::string fk_str; + if (srv_read_only_mode) { return; } @@ -812,8 +816,9 @@ row_ins_foreign_report_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + fk_str = dict_print_info_on_foreign_key_in_create_format(trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); putc('\n', ef); fputs(errstr, ef); fputs(" in parent table, in index ", ef); @@ -853,6 +858,8 @@ row_ins_foreign_report_add_err( const dtuple_t* entry) /*!< in: index entry to insert in the child table */ { + std::string fk_str; + if (srv_read_only_mode) { return; } @@ -866,8 +873,9 @@ row_ins_foreign_report_add_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + fk_str = dict_print_info_on_foreign_key_in_create_format(trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); fputs("\nTrying to add in child table, in index ", ef); ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); if (entry) { @@ -1489,6 +1497,7 @@ run_again: if (!srv_read_only_mode && check_ref) { FILE* ef = dict_foreign_err_file; + std::string fk_str; row_ins_set_detailed(trx, foreign); @@ -1498,8 +1507,9 @@ run_again: ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format( - ef, trx, foreign, TRUE); + fk_str = dict_print_info_on_foreign_key_in_create_format( + trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); fputs("\nTrying to add to index ", ef); ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 68446cc85ef..2ffe18710e2 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -42,6 +42,7 @@ Created 5/11/1994 Heikki Tuuri # include "trx0trx.h" # include "ha_prototypes.h" # include "mysql_com.h" /* NAME_LEN */ +# include <string> #endif /* UNIV_HOTBACKUP */ /** A constant to prevent the compiler from optimizing ut_delay() away. */ @@ -562,6 +563,35 @@ ut_print_namel( } /**********************************************************************//** +Outputs a fixed-length string, quoted as an SQL identifier. +If the string contains a slash '/', the string will be +output as two identifiers separated by a period (.), +as in SQL database_name.identifier. */ +UNIV_INTERN +std::string +ut_get_name( +/*=========*/ + const trx_t* trx, /*!< in: transaction (NULL=no quotes) */ + ibool table_id,/*!< in: TRUE=print a table name, + FALSE=print other identifier */ + const char* name) /*!< in: name to print */ +{ + /* 2 * NAME_LEN for database and table name, + and some slack for the #mysql50# prefix and quotes */ + char buf[3 * NAME_LEN]; + const char* bufend; + ulint namelen = strlen(name); + + bufend = innobase_convert_name(buf, sizeof buf, + name, namelen, + trx ? trx->mysql_thd : NULL, + table_id); + buf[bufend-buf]='\0'; + std::string str(buf); + return str; +} + +/**********************************************************************//** Formats a table or index name, quoted as an SQL identifier. If the name contains a slash '/', the result will contain two identifiers separated by a period (.), as in SQL database_name.identifier. diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index aa0c97f6972..c2e54ec19ad 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -2,6 +2,7 @@ Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -28,6 +29,7 @@ Created 1/8/1996 Heikki Tuuri #include "fts0fts.h" #include "fil0fil.h" #include <algorithm> +#include <string> #ifdef UNIV_NONINL #include "dict0dict.ic" @@ -3464,11 +3466,13 @@ dict_foreign_error_report( dict_foreign_t* fk, /*!< in: foreign key constraint */ const char* msg) /*!< in: the error message */ { + std::string fk_str; mutex_enter(&dict_foreign_err_mutex); dict_foreign_error_report_low(file, fk->foreign_table_name); fputs(msg, file); fputs(" Constraint:\n", file); - dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE); + fk_str = dict_print_info_on_foreign_key_in_create_format(NULL, fk, TRUE); + fputs(fk_str.c_str(), file); putc('\n', file); if (fk->foreign_index) { fputs("The index in the foreign key in table is ", file); @@ -5853,16 +5857,16 @@ dict_field_print_low( Outputs info on a foreign key of a table in a format suitable for CREATE TABLE. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ dict_foreign_t* foreign, /*!< in: foreign key constraint */ ibool add_newline) /*!< in: whether to add a newline */ { const char* stripped_id; ulint i; + std::string str; if (strchr(foreign->id, '/')) { /* Strip the preceding database name from the constraint id */ @@ -5872,96 +5876,99 @@ dict_print_info_on_foreign_key_in_create_format( stripped_id = foreign->id; } - putc(',', file); + str.append(","); if (add_newline) { /* SHOW CREATE TABLE wants constraints each printed nicely on its own line, while error messages want no newlines inserted. */ - fputs("\n ", file); + str.append("\n "); } - fputs(" CONSTRAINT ", file); - ut_print_name(file, trx, FALSE, stripped_id); - fputs(" FOREIGN KEY (", file); + str.append(" CONSTRAINT "); + + str.append(ut_get_name(trx, FALSE, stripped_id)); + str.append(" FOREIGN KEY ("); for (i = 0;;) { - ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]); + str.append(ut_get_name(trx, FALSE, foreign->foreign_col_names[i])); if (++i < foreign->n_fields) { - fputs(", ", file); + str.append(", "); } else { break; } } - fputs(") REFERENCES ", file); + str.append(") REFERENCES "); if (dict_tables_have_same_db(foreign->foreign_table_name_lookup, foreign->referenced_table_name_lookup)) { /* Do not print the database name of the referenced table */ - ut_print_name(file, trx, TRUE, + str.append(ut_get_name(trx, TRUE, dict_remove_db_name( - foreign->referenced_table_name)); + foreign->referenced_table_name))); } else { - ut_print_name(file, trx, TRUE, - foreign->referenced_table_name); + str.append(ut_get_name(trx, TRUE, + foreign->referenced_table_name)); } - putc(' ', file); - putc('(', file); + str.append(" ("); for (i = 0;;) { - ut_print_name(file, trx, FALSE, - foreign->referenced_col_names[i]); + str.append(ut_get_name(trx, FALSE, + foreign->referenced_col_names[i])); + if (++i < foreign->n_fields) { - fputs(", ", file); + str.append(", "); } else { break; } } - putc(')', file); + str.append(")"); if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) { - fputs(" ON DELETE CASCADE", file); + str.append(" ON DELETE CASCADE"); } if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) { - fputs(" ON DELETE SET NULL", file); + str.append(" ON DELETE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) { - fputs(" ON DELETE NO ACTION", file); + str.append(" ON DELETE NO ACTION"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { - fputs(" ON UPDATE CASCADE", file); + str.append(" ON UPDATE CASCADE"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { - fputs(" ON UPDATE SET NULL", file); + str.append(" ON UPDATE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) { - fputs(" ON UPDATE NO ACTION", file); + str.append(" ON UPDATE NO ACTION"); } + + return str; } /**********************************************************************//** Outputs info on foreign keys of a table. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_keys( /*============================*/ ibool create_table_format, /*!< in: if TRUE then print in a format suitable to be inserted into a CREATE TABLE, otherwise in the format of SHOW TABLE STATUS */ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ dict_table_t* table) /*!< in: table */ { dict_foreign_t* foreign; + std::string str; mutex_enter(&(dict_sys->mutex)); @@ -5972,64 +5979,67 @@ dict_print_info_on_foreign_keys( foreign = *it; if (create_table_format) { - dict_print_info_on_foreign_key_in_create_format( - file, trx, foreign, TRUE); + str.append( + dict_print_info_on_foreign_key_in_create_format( + trx, foreign, TRUE)); } else { ulint i; - fputs("; (", file); + str.append("; ("); for (i = 0; i < foreign->n_fields; i++) { if (i) { - putc(' ', file); + str.append(" "); } - ut_print_name(file, trx, FALSE, - foreign->foreign_col_names[i]); + str.append(ut_get_name(trx, FALSE, + foreign->foreign_col_names[i])); } - fputs(") REFER ", file); - ut_print_name(file, trx, TRUE, - foreign->referenced_table_name); - putc('(', file); + str.append(") REFER "); + str.append(ut_get_name(trx, TRUE, + foreign->referenced_table_name)); + str.append(")"); for (i = 0; i < foreign->n_fields; i++) { if (i) { - putc(' ', file); + str.append(" "); } - ut_print_name( - file, trx, FALSE, - foreign->referenced_col_names[i]); + str.append(ut_get_name( + trx, FALSE, + foreign->referenced_col_names[i])); } - putc(')', file); + str.append(")"); if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) { - fputs(" ON DELETE CASCADE", file); + str.append(" ON DELETE CASCADE"); } if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) { - fputs(" ON DELETE SET NULL", file); + str.append(" ON DELETE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) { - fputs(" ON DELETE NO ACTION", file); + str.append(" ON DELETE NO ACTION"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { - fputs(" ON UPDATE CASCADE", file); + str.append(" ON UPDATE CASCADE"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { - fputs(" ON UPDATE SET NULL", file); + str.append(" ON UPDATE SET NULL"); } if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) { - fputs(" ON UPDATE NO ACTION", file); + str.append(" ON UPDATE NO ACTION"); } } } mutex_exit(&(dict_sys->mutex)); + + return str; } /********************************************************************//** diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 191a37906da..348e7107009 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -116,6 +116,9 @@ this program; if not, write to the Free Software Foundation, Inc., #include "i_s.h" #include "xtradb_i_s.h" +#include <string> +#include <sstream> + # ifndef MYSQL_PLUGIN_IMPORT # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ @@ -12712,8 +12715,9 @@ ha_innobase::update_table_comment( const char* comment)/*!< in: table comment defined by user */ { uint length = (uint) strlen(comment); - char* str; + char* str=0; long flen; + std::string fk_str; /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -12731,50 +12735,40 @@ ha_innobase::update_table_comment( possible adaptive hash latch to avoid deadlocks of threads */ trx_search_latch_release_if_reserved(prebuilt->trx); - str = NULL; - - /* output the data to a temporary file */ - if (!srv_read_only_mode) { - - mutex_enter(&srv_dict_tmpfile_mutex); +#define SSTR( x ) reinterpret_cast< std::ostringstream & >( \ + ( std::ostringstream() << std::dec << x ) ).str() - rewind(srv_dict_tmpfile); + fk_str.append("InnoDB free: "); + fk_str.append(SSTR(fsp_get_available_space_in_free_extents( + prebuilt->table->space))); - fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB", - fsp_get_available_space_in_free_extents( - prebuilt->table->space)); + fk_str.append(dict_print_info_on_foreign_keys( + FALSE, prebuilt->trx, + prebuilt->table)); - dict_print_info_on_foreign_keys( - FALSE, srv_dict_tmpfile, prebuilt->trx, - prebuilt->table); + flen = fk_str.length(); - flen = ftell(srv_dict_tmpfile); - - if (flen < 0) { - flen = 0; - } else if (length + flen + 3 > 64000) { - flen = 64000 - 3 - length; - } + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { + flen = 64000 - 3 - length; + } - /* allocate buffer for the full string, and - read the contents of the temporary file */ + /* allocate buffer for the full string */ - str = (char*) my_malloc(length + flen + 3, MYF(0)); + str = (char*) my_malloc(length + flen + 3, MYF(0)); - if (str) { - char* pos = str + length; - if (length) { - memcpy(str, comment, length); - *pos++ = ';'; - *pos++ = ' '; - } - rewind(srv_dict_tmpfile); - flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile); - pos[flen] = 0; + if (str) { + char* pos = str + length; + if (length) { + memcpy(str, comment, length); + *pos++ = ';'; + *pos++ = ' '; } - mutex_exit(&srv_dict_tmpfile_mutex); + memcpy(pos, fk_str.c_str(), flen); + pos[flen] = 0; } prebuilt->trx->op_info = (char*)""; @@ -12792,8 +12786,7 @@ char* ha_innobase::get_foreign_key_create_info(void) /*==========================================*/ { - long flen; - char* str = 0; + char* fk_str = 0; ut_a(prebuilt != NULL); @@ -12811,38 +12804,22 @@ ha_innobase::get_foreign_key_create_info(void) trx_search_latch_release_if_reserved(prebuilt->trx); - if (!srv_read_only_mode) { - mutex_enter(&srv_dict_tmpfile_mutex); - rewind(srv_dict_tmpfile); - - /* Output the data to a temporary file */ - dict_print_info_on_foreign_keys( - TRUE, srv_dict_tmpfile, prebuilt->trx, + /* Output the data to a temporary file */ + std::string str = dict_print_info_on_foreign_keys( + TRUE, prebuilt->trx, prebuilt->table); - prebuilt->trx->op_info = (char*)""; - - flen = ftell(srv_dict_tmpfile); - - if (flen < 0) { - flen = 0; - } - - /* Allocate buffer for the string, and - read the contents of the temporary file */ - - str = (char*) my_malloc(flen + 1, MYF(0)); + prebuilt->trx->op_info = (char*)""; - if (str) { - rewind(srv_dict_tmpfile); - flen = (uint) fread(str, 1, flen, srv_dict_tmpfile); - str[flen] = 0; - } + /* Allocate buffer for the string */ + fk_str = (char*) my_malloc(str.length() + 1, MYF(0)); - mutex_exit(&srv_dict_tmpfile_mutex); + if (fk_str) { + memcpy(fk_str, str.c_str(), str.length()); + fk_str[str.length()]='\0'; } - return(str); + return(fk_str); } diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h index 524c1381d58..0e8498e6210 100644 --- a/storage/xtradb/include/dict0dict.h +++ b/storage/xtradb/include/dict0dict.h @@ -2,6 +2,7 @@ Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -624,29 +625,25 @@ dict_table_print( /**********************************************************************//** Outputs info on foreign keys of a table. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_keys( /*============================*/ ibool create_table_format, /*!< in: if TRUE then print in a format suitable to be inserted into a CREATE TABLE, otherwise in the format of SHOW TABLE STATUS */ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ - dict_table_t* table) /*!< in: table */ - __attribute__((nonnull)); + dict_table_t* table); /*!< in: table */ /**********************************************************************//** Outputs info on a foreign key of a table in a format suitable for CREATE TABLE. */ UNIV_INTERN -void +std::string dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /*!< in: file where to print */ trx_t* trx, /*!< in: transaction */ dict_foreign_t* foreign, /*!< in: foreign key constraint */ - ibool add_newline) /*!< in: whether to add a newline */ - __attribute__((nonnull(1,3))); + ibool add_newline); /*!< in: whether to add a newline */ /********************************************************************//** Displays the names of the index and the table. */ UNIV_INTERN diff --git a/storage/xtradb/include/ut0ut.h b/storage/xtradb/include/ut0ut.h index 0caf379d8fa..9228c25d8be 100644 --- a/storage/xtradb/include/ut0ut.h +++ b/storage/xtradb/include/ut0ut.h @@ -43,6 +43,8 @@ Created 1/20/1994 Heikki Tuuri #include <stdarg.h> /* for va_list */ +#include <string> + /** Index name prefix in fast index creation */ #define TEMP_INDEX_PREFIX '\377' /** Index name prefix in fast index creation, as a string constant */ @@ -390,7 +392,19 @@ ut_print_namel( FALSE=print other identifier */ const char* name, /*!< in: name to print */ ulint namelen);/*!< in: length of name */ - +/**********************************************************************//** +Outputs a fixed-length string, quoted as an SQL identifier. +If the string contains a slash '/', the string will be +output as two identifiers separated by a period (.), +as in SQL database_name.identifier. */ +UNIV_INTERN +std::string +ut_get_name( +/*=========*/ + const trx_t* trx, /*!< in: transaction (NULL=no quotes) */ + ibool table_id,/*!< in: TRUE=print a table name, + FALSE=print other identifier */ + const char* name); /*!< in: name to print */ /**********************************************************************//** Formats a table or index name, quoted as an SQL identifier. If the name contains a slash '/', the result will contain two identifiers separated by diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index 6d9c2bdc908..10390385844 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -736,10 +736,12 @@ row_ins_set_detailed( rewind(srv_misc_tmpfile); if (os_file_set_eof(srv_misc_tmpfile)) { + std::string fk_str; ut_print_name(srv_misc_tmpfile, trx, TRUE, foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format( - srv_misc_tmpfile, trx, foreign, FALSE); + fk_str = dict_print_info_on_foreign_key_in_create_format( + trx, foreign, FALSE); + fputs(fk_str.c_str(), srv_misc_tmpfile); trx_set_detailed_error_from_file(trx, srv_misc_tmpfile); } else { trx_set_detailed_error(trx, "temp file operation failed"); @@ -804,6 +806,8 @@ row_ins_foreign_report_err( const dtuple_t* entry) /*!< in: index entry in the parent table */ { + std::string fk_str; + if (srv_read_only_mode) { return; } @@ -818,8 +822,9 @@ row_ins_foreign_report_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + fk_str = dict_print_info_on_foreign_key_in_create_format(trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); putc('\n', ef); fputs(errstr, ef); fputs(" in parent table, in index ", ef); @@ -859,6 +864,8 @@ row_ins_foreign_report_add_err( const dtuple_t* entry) /*!< in: index entry to insert in the child table */ { + std::string fk_str; + if (srv_read_only_mode) { return; } @@ -872,8 +879,9 @@ row_ins_foreign_report_add_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + fk_str = dict_print_info_on_foreign_key_in_create_format(trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); fputs("\nTrying to add in child table, in index ", ef); ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); if (entry) { @@ -1495,6 +1503,7 @@ run_again: if (!srv_read_only_mode && check_ref) { FILE* ef = dict_foreign_err_file; + std::string fk_str; row_ins_set_detailed(trx, foreign); @@ -1504,8 +1513,9 @@ run_again: ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format( - ef, trx, foreign, TRUE); + fk_str = dict_print_info_on_foreign_key_in_create_format( + trx, foreign, TRUE); + fputs(fk_str.c_str(), ef); fputs("\nTrying to add to index ", ef); ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); diff --git a/storage/xtradb/ut/ut0ut.cc b/storage/xtradb/ut/ut0ut.cc index 121cbdb7bc0..3de3d6e5ee6 100644 --- a/storage/xtradb/ut/ut0ut.cc +++ b/storage/xtradb/ut/ut0ut.cc @@ -43,6 +43,7 @@ Created 5/11/1994 Heikki Tuuri # include "trx0trx.h" # include "ha_prototypes.h" # include "mysql_com.h" /* NAME_LEN */ +# include <string> #endif /* UNIV_HOTBACKUP */ /** A constant to prevent the compiler from optimizing ut_delay() away. */ @@ -563,6 +564,35 @@ ut_print_namel( } /**********************************************************************//** +Outputs a fixed-length string, quoted as an SQL identifier. +If the string contains a slash '/', the string will be +output as two identifiers separated by a period (.), +as in SQL database_name.identifier. */ +UNIV_INTERN +std::string +ut_get_name( +/*=========*/ + const trx_t* trx, /*!< in: transaction (NULL=no quotes) */ + ibool table_id,/*!< in: TRUE=print a table name, + FALSE=print other identifier */ + const char* name) /*!< in: name to print */ +{ + /* 2 * NAME_LEN for database and table name, + and some slack for the #mysql50# prefix and quotes */ + char buf[3 * NAME_LEN]; + const char* bufend; + ulint namelen = strlen(name); + + bufend = innobase_convert_name(buf, sizeof buf, + name, namelen, + trx ? trx->mysql_thd : NULL, + table_id); + buf[bufend-buf]='\0'; + std::string str(buf); + return str; +} + +/**********************************************************************//** Formats a table or index name, quoted as an SQL identifier. If the name contains a slash '/', the result will contain two identifiers separated by a period (.), as in SQL database_name.identifier. |