Fixed bug #28244.

When the same VIEW was created at the master side twice,
malformed (truncated after the word 'AS') query string 
was forwarded to client side, so error messages on the
master and client was different, and replication was
broken.

The mysql_register_view function call failed
too early: fields of `view' output argument of this 
function was not filled yet with correct data required
for query replication.
The mysql_register_view function also copied pointers to 
local buffers into a memory allocated by the caller.
parent bed482c2
......@@ -106,4 +106,10 @@ a b
1 6
drop table t1;
drop view v1;
CREATE TABLE t1(a INT);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE VIEW v1 AS SELECT * FROM t1;
ERROR 42S01: Table 'v1' already exists
DROP VIEW v1;
DROP TABLE t1;
End of 5.0 tests
......@@ -149,4 +149,16 @@ drop view v1;
sync_slave_with_master;
#
# BUG#28244 CREATE VIEW breaks replication when view exists
#
connection master;
CREATE TABLE t1(a INT);
CREATE VIEW v1 AS SELECT * FROM t1;
--error ER_TABLE_EXISTS_ERROR
CREATE VIEW v1 AS SELECT * FROM t1;
DROP VIEW v1;
DROP TABLE t1;
sync_slave_with_master;
--echo End of 5.0 tests
......@@ -692,6 +692,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
bool can_be_merged;
char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
LEX_STRING dir, file;
int error= 0;
DBUG_ENTER("mysql_register_view");
/* print query */
......@@ -702,9 +703,57 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
lex->unit.print(&str);
thd->variables.sql_mode|= sql_mode;
}
str.append('\0');
DBUG_PRINT("info", ("View: %s", str.ptr()));
/* fill structure */
view->query.str= str.c_ptr();
view->query.length= str.length();
view->source.str= thd->query + thd->lex->create_view_select_start;
view->source.length= skip_rear_comments((char *)view->source.str,
(char *)thd->query +
thd->query_length) -
view->source.str;
view->file_version= 1;
view->calc_md5(md5);
view->md5.str= md5;
view->md5.length= 32;
can_be_merged= lex->can_be_merged();
if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE &&
!lex->can_be_merged())
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE,
ER(ER_WARN_VIEW_MERGE));
lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
}
view->algorithm= lex->create_view_algorithm;
view->definer.user= lex->definer->user;
view->definer.host= lex->definer->host;
view->view_suid= lex->create_view_suid;
view->with_check= lex->create_view_check;
if ((view->updatable_view= (can_be_merged &&
view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
{
/* TODO: change here when we will support UNIONs */
for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first;
tbl;
tbl= tbl->next_local)
{
if ((tbl->view && !tbl->updatable_view) || tbl->schema_table)
{
view->updatable_view= 0;
break;
}
for (TABLE_LIST *up= tbl; up; up= up->embedding)
{
if (up->outer_join)
{
view->updatable_view= 0;
goto loop_out;
}
}
}
}
loop_out:
/* print file name */
(void) my_snprintf(dir_buff, FN_REFLEN, "%s/%s/",
mysql_data_home, view->db);
......@@ -734,16 +783,21 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
if (mode == VIEW_CREATE_NEW)
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias);
DBUG_RETURN(-1);
error= -1;
goto err;
}
if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0)))
DBUG_RETURN(1);
{
error= 1;
goto err;
}
if (!parser->ok() || !is_equal(&view_type, parser->type()))
{
my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW");
DBUG_RETURN(-1);
error= -1;
goto err;
}
/*
......@@ -756,7 +810,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
view_parameters + revision_number_position, 1,
&file_parser_dummy_hook))
{
DBUG_RETURN(thd->net.report_error? -1 : 0);
error= thd->net.report_error? -1 : 0;
goto err;
}
}
else
......@@ -764,59 +819,11 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
if (mode == VIEW_ALTER)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias);
DBUG_RETURN(-1);
}
}
}
/* fill structure */
view->query.str= (char*)str.ptr();
view->query.length= str.length()-1; // we do not need last \0
view->source.str= thd->query + thd->lex->create_view_select_start;
view->source.length= (char *)skip_rear_comments((char *)view->source.str,
(char *)thd->query +
thd->query_length) -
view->source.str;
view->file_version= 1;
view->calc_md5(md5);
view->md5.str= md5;
view->md5.length= 32;
can_be_merged= lex->can_be_merged();
if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE &&
!lex->can_be_merged())
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE,
ER(ER_WARN_VIEW_MERGE));
lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
}
view->algorithm= lex->create_view_algorithm;
view->definer.user= lex->definer->user;
view->definer.host= lex->definer->host;
view->view_suid= lex->create_view_suid;
view->with_check= lex->create_view_check;
if ((view->updatable_view= (can_be_merged &&
view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
{
/* TODO: change here when we will support UNIONs */
for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first;
tbl;
tbl= tbl->next_local)
{
if ((tbl->view && !tbl->updatable_view) || tbl->schema_table)
{
view->updatable_view= 0;
break;
}
for (TABLE_LIST *up= tbl; up; up= up->embedding)
{
if (up->outer_join)
{
view->updatable_view= 0;
goto loop_out;
}
error= -1;
goto err;
}
}
}
loop_out:
/*
Check that table of main select do not used in subqueries.
......@@ -841,15 +848,23 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
!view->updatable_view)
{
my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->table_name);
DBUG_RETURN(-1);
error= -1;
goto err;
}
if (sql_create_definition_file(&dir, &file, view_file_type,
(gptr)view, view_parameters, num_view_backups))
{
DBUG_RETURN(thd->net.report_error? -1 : 1);
error= thd->net.report_error? -1 : 1;
goto err;
}
DBUG_RETURN(0);
err:
view->query.str= NULL;
view->query.length= 0;
view->md5.str= NULL;
view->md5.length= NULL;
DBUG_RETURN(error);
}
......
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