summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2015-12-14 14:34:32 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2015-12-14 22:10:37 +0200
commit99404c3437b35b5ee51578c2ea74209ccb9ba890 (patch)
tree7dc58eefe89b0d799589d2ca3d95a452e6e69916 /storage
parent0db50be89349761d5677441f2d60ab52c23947f0 (diff)
downloadmariadb-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.cc110
-rw-r--r--storage/innobase/handler/ha_innodb.cc103
-rw-r--r--storage/innobase/include/dict0dict.h13
-rw-r--r--storage/innobase/include/ut0ut.h16
-rw-r--r--storage/innobase/row/row0ins.cc22
-rw-r--r--storage/innobase/ut/ut0ut.cc30
-rw-r--r--storage/xtradb/dict/dict0dict.cc110
-rw-r--r--storage/xtradb/handler/ha_innodb.cc103
-rw-r--r--storage/xtradb/include/dict0dict.h13
-rw-r--r--storage/xtradb/include/ut0ut.h16
-rw-r--r--storage/xtradb/row/row0ins.cc22
-rw-r--r--storage/xtradb/ut/ut0ut.cc30
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.