[Commits] 9eb15a56: MDEV-9276: MySQL Bug #78754: FK definitions missing from SHOW CREATE TABLE in "innodb_read_only" mode

Jan Lindström jan.lindstrom at mariadb.com
Mon Dec 14 14:35:04 EET 2015


revision-id: 9eb15a566953fe62c0af3638a26ea88505df21a3 (mariadb-10.0.22-57-g9eb15a56)
parent(s): 3e206a518dec400e084451165f633b78eb2e7fee
committer: Jan Lindström
timestamp: 2015-12-14 14:34:32 +0200
message:

MDEV-9276: MySQL Bug #78754: FK definitions missing from SHOW CREATE TABLE in "innodb_read_only" mode

---
 mysql-test/suite/innodb/r/innodb-get-fk.result |  71 ++++++++++++++++
 mysql-test/suite/innodb/t/innodb-get-fk.test   |  61 ++++++++++++++
 storage/innobase/dict/dict0dict.cc             | 110 ++++++++++++++-----------
 storage/innobase/handler/ha_innodb.cc          | 103 +++++++++--------------
 storage/innobase/include/dict0dict.h           |  13 ++-
 storage/innobase/include/ut0ut.h               |  16 +++-
 storage/innobase/row/row0ins.cc                |  22 +++--
 storage/innobase/ut/ut0ut.cc                   |  30 +++++++
 storage/xtradb/dict/dict0dict.cc               | 110 ++++++++++++++-----------
 storage/xtradb/handler/ha_innodb.cc            | 103 +++++++++--------------
 storage/xtradb/include/dict0dict.h             |  13 ++-
 storage/xtradb/include/ut0ut.h                 |  16 +++-
 storage/xtradb/row/row0ins.cc                  |  22 +++--
 storage/xtradb/ut/ut0ut.cc                     |  30 +++++++
 14 files changed, 464 insertions(+), 256 deletions(-)

diff --git a/mysql-test/suite/innodb/r/innodb-get-fk.result b/mysql-test/suite/innodb/r/innodb-get-fk.result
new file mode 100644
index 0000000..0dca82c
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-get-fk.result
@@ -0,0 +1,71 @@
+CREATE SCHEMA `repro`;
+CREATE TABLE `repro`.`crew` (
+`id` int(11) NOT NULL AUTO_INCREMENT,
+`code` varchar(50) NOT NULL,
+`name` varchar(50) NOT NULL,
+`created_at` timestamp NULL DEFAULT NULL,
+`updated_at` timestamp NULL DEFAULT NULL,
+PRIMARY KEY (`id`),
+KEY `code` (`code`)
+) ENGINE=InnoDB;
+CREATE TABLE `repro`.`pilot` (
+`id` int(11) NOT NULL AUTO_INCREMENT,
+`code` varchar(50) NOT NULL,
+`name` varchar(50) NOT NULL,
+`created_at` timestamp NULL DEFAULT NULL,
+`updated_at` timestamp NULL DEFAULT NULL,
+PRIMARY KEY (`id`),
+KEY `code` (`code`)
+) ENGINE=InnoDB;
+CREATE TABLE `repro`.`crew_role_assigned` (
+`id` int(11) NOT NULL AUTO_INCREMENT,
+`crew_id` int(11) NOT NULL,
+`role_code` varchar(50) NOT NULL,
+PRIMARY KEY (`id`),
+KEY `fk_crewRoleAssigned_roleCode` (`role_code`),
+CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`crew` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB COMMENT="This is a comment about tables";
+# Restart mysqld --innodb_read_only_mode=1
+SHOW CREATE TABLE `repro`.`crew_role_assigned`;
+Table	Create Table
+crew_role_assigned	CREATE TABLE `crew_role_assigned` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `crew_id` int(11) NOT NULL,
+  `role_code` varchar(50) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `fk_crewRoleAssigned_roleCode` (`role_code`),
+  KEY `fk_crewRoleAssigned_pilotId` (`crew_id`),
+  CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `crew` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This is a comment about tables'
+ALTER TABLE `repro`.`crew_role_assigned` COMMENT = "This is a new comment about tables";
+SHOW CREATE TABLE `repro`.`crew_role_assigned`;
+Table	Create Table
+crew_role_assigned	CREATE TABLE `crew_role_assigned` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `crew_id` int(11) NOT NULL,
+  `role_code` varchar(50) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `fk_crewRoleAssigned_roleCode` (`role_code`),
+  KEY `fk_crewRoleAssigned_pilotId` (`crew_id`),
+  CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `crew` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This is a new comment about tables'
+# Restart mysqld --innodb_read_only_mode=1
+SHOW CREATE TABLE `repro`.`crew_role_assigned`;
+Table	Create Table
+crew_role_assigned	CREATE TABLE `crew_role_assigned` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `crew_id` int(11) NOT NULL,
+  `role_code` varchar(50) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `fk_crewRoleAssigned_roleCode` (`role_code`),
+  KEY `fk_crewRoleAssigned_pilotId` (`crew_id`),
+  CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `crew` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This is a new comment about tables'
+DROP TABLE `repro`.`crew_role_assigned`;
+DROP TABLE `repro`.`pilot`;
+DROP TABLE `repro`.`crew`;
+DROP SCHEMA `repro`;
diff --git a/mysql-test/suite/innodb/t/innodb-get-fk.test b/mysql-test/suite/innodb/t/innodb-get-fk.test
new file mode 100644
index 0000000..4245bef
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-get-fk.test
@@ -0,0 +1,61 @@
+-- source include/have_innodb.inc
+# need to restart server
+-- source include/not_embedded.inc
+CREATE SCHEMA `repro`;
+
+CREATE TABLE `repro`.`crew` (
+`id` int(11) NOT NULL AUTO_INCREMENT,
+`code` varchar(50) NOT NULL,
+`name` varchar(50) NOT NULL,
+`created_at` timestamp NULL DEFAULT NULL,
+`updated_at` timestamp NULL DEFAULT NULL,
+PRIMARY KEY (`id`),
+KEY `code` (`code`)
+) ENGINE=InnoDB;
+
+CREATE TABLE `repro`.`pilot` (
+`id` int(11) NOT NULL AUTO_INCREMENT,
+`code` varchar(50) NOT NULL,
+`name` varchar(50) NOT NULL,
+`created_at` timestamp NULL DEFAULT NULL,
+`updated_at` timestamp NULL DEFAULT NULL,
+PRIMARY KEY (`id`),
+KEY `code` (`code`)
+) ENGINE=InnoDB;
+
+CREATE TABLE `repro`.`crew_role_assigned` (
+`id` int(11) NOT NULL AUTO_INCREMENT,
+`crew_id` int(11) NOT NULL,
+`role_code` varchar(50) NOT NULL,
+PRIMARY KEY (`id`),
+KEY `fk_crewRoleAssigned_roleCode` (`role_code`),
+CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`crew` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB COMMENT="This is a comment about tables";
+
+--echo # Restart mysqld --innodb_read_only_mode=1
+-- let $restart_parameters=--innodb-read-only-mode=1
+-- source include/restart_mysqld.inc
+
+SHOW CREATE TABLE `repro`.`crew_role_assigned`;
+
+-- source include/restart_mysqld.inc
+
+ALTER TABLE `repro`.`crew_role_assigned` COMMENT = "This is a new comment about tables";
+SHOW CREATE TABLE `repro`.`crew_role_assigned`;
+
+--echo # Restart mysqld --innodb_read_only_mode=1
+-- let $restart_parameters=--innodb-read-only-mode=1
+-- source include/restart_mysqld.inc
+
+#
+# Below create table should contain also fk definitions
+#
+SHOW CREATE TABLE `repro`.`crew_role_assigned`;
+
+-- source include/restart_mysqld.inc
+
+DROP TABLE `repro`.`crew_role_assigned`;
+DROP TABLE `repro`.`pilot`;
+DROP TABLE `repro`.`crew`;
+DROP SCHEMA `repro`;
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 09893d2..b5e97a2 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 f6c2a08..fde5683 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 5266cf7..4332867 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 939ccee..32a4d97 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 9f22889..e75a039 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 @@ row_ins_check_foreign_constraint(
 
 		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 @@ row_ins_check_foreign_constraint(
 			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 68446cc..2ffe187 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 aa0c97f..c2e54ec 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 191a379..348e710 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 524c138..0e8498e 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 0caf379..9228c25 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 6d9c2bd..1039038 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 @@ row_ins_check_foreign_constraint(
 
 		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 @@ row_ins_check_foreign_constraint(
 			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 121cbdb..3de3d6e 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.



More information about the commits mailing list