Commit 2a846fa2 authored by unknown's avatar unknown

Fix for BUG#30027: mysqldump does not dump views properly.

mysqldump generates view defitions in two stages:

  - dump CREATE TABLE statements for the temporary tables.  For each view a
    temporary table, that has the same structure as the view is created.

  - dump DROP TABLE statements for the temporary tables and CREATE VIEW
    statements for the view.

This approach is required because views can have dependencies on each other
(a view can use other views). So, they should be created in the particular
order. mysqldump however is not smart enough, so in order to resolve
dependencies it creates temporary tables first of all.

The problem was that mysqldump might have generated incorrect dump for the
temporary table when a view has non-ASCII column name. That happened when
default-character-set is not utf8.

The fix is to:

  1. Switch character_set_client for the mysqldump's connection to binary
     before issuing SHOW FIELDS statement in order to avoid conversion.
    
  2. Dump switch character_set_client statements to UTF8 and back for
     CREATE TABLE statement that is issued to create temporary table.


client/mysqldump.c:
  1. Switch character_set_results for mysqldump's connection to
  binary before SHOW FIELDS in order to avoid conversion to client
  character set.
  
  2. Dump switch character_set_client statements to UTF8 and back
  for CREATE TABLE statement.
mysql-test/r/mysqldump.result:
  Update result file.
mysql-test/t/mysqldump.test:
  Test case for BUG#30027.
parent b70262d6
......@@ -2174,7 +2174,9 @@ static uint get_table_structure(char *table, char *db, char *table_type,
*/
my_snprintf(query_buff, sizeof(query_buff),
"SHOW FIELDS FROM %s", result_table);
if (mysql_query_with_error_report(mysql, 0, query_buff))
if (switch_character_set_results(mysql, "binary") ||
mysql_query_with_error_report(mysql, &result, query_buff) ||
switch_character_set_results(mysql, default_charset))
{
/*
View references invalid or privileged table/col/fun (err 1356),
......@@ -2192,43 +2194,50 @@ static uint get_table_structure(char *table, char *db, char *table_type,
else
my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
if ((result= mysql_store_result(mysql)))
if (mysql_num_rows(result))
{
if (mysql_num_rows(result))
if (opt_drop)
{
if (opt_drop)
{
/*
We have already dropped any table of the same name
above, so here we just drop the view.
*/
We have already dropped any table of the same name above, so
here we just drop the view.
*/
fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
opt_quoted_table);
check_io(sql_file);
}
fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
opt_quoted_table);
check_io(sql_file);
}
fprintf(sql_file, "/*!50001 CREATE TABLE %s (\n", result_table);
/*
Get first row, following loop will prepend comma - keeps
from having to know if the row being printed is last to
determine if there should be a _trailing_ comma.
*/
row= mysql_fetch_row(result);
fprintf(sql_file,
"SET @saved_cs_client = @@character_set_client;\n"
"SET character_set_client = utf8;\n"
"/*!50001 CREATE TABLE %s (\n",
result_table);
/*
Get first row, following loop will prepend comma - keeps from
having to know if the row being printed is last to determine if
there should be a _trailing_ comma.
*/
fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0),
row[1]);
row= mysql_fetch_row(result);
while((row= mysql_fetch_row(result)))
{
/* col name, col type */
fprintf(sql_file, ",\n %s %s",
quote_name(row[0], name_buff, 0), row[1]);
}
fprintf(sql_file, "\n) */;\n");
check_io(sql_file);
fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0),
row[1]);
while((row= mysql_fetch_row(result)))
{
/* col name, col type */
fprintf(sql_file, ",\n %s %s",
quote_name(row[0], name_buff, 0), row[1]);
}
fprintf(sql_file,
"\n) */;\n"
"SET character_set_client = @saved_cs_client;\n");
check_io(sql_file);
}
mysql_free_result(result);
if (path)
......
......@@ -1887,9 +1887,12 @@ INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon');
UNLOCK TABLES;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v2` (
`a` varchar(30)
) */;
SET character_set_client = @saved_cs_client;
/*!50001 DROP TABLE `v2`*/;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
......@@ -1978,9 +1981,12 @@ LOCK TABLES `t1` WRITE;
UNLOCK TABLES;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v1` (
`a` int(11)
) */;
SET character_set_client = @saved_cs_client;
/*!50001 DROP TABLE `v1`*/;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
......@@ -2046,9 +2052,12 @@ INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon');
UNLOCK TABLES;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v2` (
`a` varchar(30)
) */;
SET character_set_client = @saved_cs_client;
/*!50001 DROP TABLE `v2`*/;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
......@@ -2151,23 +2160,32 @@ INSERT INTO `t1` VALUES (1,2,'one'),(2,4,'two'),(3,6,'three');
UNLOCK TABLES;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v1` (
`a` int(11),
`b` int(11),
`c` varchar(30)
) */;
SET character_set_client = @saved_cs_client;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v2` (
`a` int(11)
) */;
SET character_set_client = @saved_cs_client;
DROP TABLE IF EXISTS `v3`;
/*!50001 DROP VIEW IF EXISTS `v3`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v3` (
`a` int(11),
`b` int(11),
`c` varchar(30)
) */;
SET character_set_client = @saved_cs_client;
/*!50001 DROP TABLE `v1`*/;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
......@@ -2867,25 +2885,34 @@ INSERT INTO `t1` VALUES (1,'first value','xxxx'),(2,'second value','tttt'),(3,'t
UNLOCK TABLES;
DROP TABLE IF EXISTS `v0`;
/*!50001 DROP VIEW IF EXISTS `v0`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v0` (
`a` int(11),
`b` varchar(32),
`c` varchar(32)
) */;
SET character_set_client = @saved_cs_client;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v1` (
`a` int(11),
`b` varchar(32),
`c` varchar(32)
) */;
SET character_set_client = @saved_cs_client;
DROP TABLE IF EXISTS `v2`;
/*!50001 DROP VIEW IF EXISTS `v2`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v2` (
`a` int(11),
`b` varchar(32),
`c` varchar(32)
) */;
SET character_set_client = @saved_cs_client;
USE `test`;
/*!50001 DROP TABLE `v0`*/;
......@@ -3248,9 +3275,12 @@ INSERT INTO `t1` VALUES (1232131),(4711),(3231),(815);
UNLOCK TABLES;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v1` (
`id` int(11)
) */;
SET character_set_client = @saved_cs_client;
USE `mysqldump_test_db`;
/*!50001 DROP TABLE `v1`*/;
......@@ -3302,9 +3332,12 @@ CREATE TABLE `basetable` (
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_views` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `mysqldump_views`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `nasishnasifu` (
`id` bigint(20) unsigned
) */;
SET character_set_client = @saved_cs_client;
USE `mysqldump_tables`;
......@@ -3870,9 +3903,12 @@ INSERT INTO `t1` VALUES (1232131),(4711),(3231),(815);
UNLOCK TABLES;
DROP TABLE IF EXISTS `v1`;
/*!50001 DROP VIEW IF EXISTS `v1`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE TABLE `v1` (
`id` int(11)
) */;
SET character_set_client = @saved_cs_client;
USE `mysqldump_test_db`;
/*!50001 DROP TABLE `v1`*/;
......@@ -3903,5 +3939,38 @@ drop view v1;
drop table t1;
drop database mysqldump_test_db;
#
# Bug #30027: mysqldump does not dump views properly.
#
# Cleanup.
DROP DATABASE IF EXISTS mysqldump_test_db;
# Create objects.
CREATE DATABASE mysqldump_test_db;
set names koi8r;
CREATE VIEW mysqldump_test_db.v2 AS SELECT 1 AS 1;
CREATE VIEW mysqldump_test_db.v1 AS SELECT 1 FROM mysqldump_test_db.v2;
set names latin1;
# Dump mysqldump_test_db to /dev/shm/t1/var/tmp/bug30027.sql.
# Drop mysqldump_test_db.
DROP DATABASE mysqldump_test_db;
# Restore mysqldump_test_db from /dev/shm/t1/var/tmp/bug30027.sql.
# Check the view.
set names utf8;
SHOW CREATE VIEW mysqldump_test_db.v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqldump_test_db`.`v1` AS select `v2`.`колонка1` AS `колонка1` from `mysqldump_test_db`.`v2` koi8r koi8r_general_ci
SHOW CREATE VIEW mysqldump_test_db.v2;
View Create View character_set_client collation_connection
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqldump_test_db`.`v2` AS select 1 AS `колонка1` koi8r koi8r_general_ci
set names latin1;
# Cleanup.
DROP DATABASE mysqldump_test_db;
#
# End of 5.1 tests
#
......@@ -1676,6 +1676,64 @@ drop database mysqldump_test_db;
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug26121.sql
--remove_file $MYSQLTEST_VARDIR/tmp/bug26121.sql
###########################################################################
--echo #
--echo # Bug #30027: mysqldump does not dump views properly.
--echo #
--echo
--echo # Cleanup.
--disable_warnings
DROP DATABASE IF EXISTS mysqldump_test_db;
--enable_warnings
--echo
--echo # Create objects.
CREATE DATABASE mysqldump_test_db;
set names koi8r;
CREATE VIEW mysqldump_test_db.v2 AS SELECT 1 AS 1;
CREATE VIEW mysqldump_test_db.v1 AS SELECT 1 FROM mysqldump_test_db.v2;
set names latin1;
--echo
--echo # Dump mysqldump_test_db to $MYSQLTEST_VARDIR/tmp/bug30027.sql.
--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --default-character-set=latin1 --databases mysqldump_test_db > $MYSQLTEST_VARDIR/tmp/bug30027.sql
# --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --databases mysqldump_test_db > $MYSQLTEST_VARDIR/tmp/bug30027.sql
--echo
--echo # Drop mysqldump_test_db.
DROP DATABASE mysqldump_test_db;
--echo
--echo # Restore mysqldump_test_db from $MYSQLTEST_VARDIR/tmp/bug30027.sql.
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug30027.sql
--echo
--echo # Check the view.
set names utf8;
SHOW CREATE VIEW mysqldump_test_db.v1;
SHOW CREATE VIEW mysqldump_test_db.v2;
set names latin1;
--echo
--echo # Cleanup.
DROP DATABASE mysqldump_test_db;
###########################################################################
--echo #
--echo # End of 5.1 tests
--echo #
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment