diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result index f5ddb9e13ba..0d862a2a912 100644 --- a/mysql-test/r/rpl_view.result +++ b/mysql-test/r/rpl_view.result @@ -95,4 +95,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 diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test index 3eff8f7550a..51ad319b212 100644 --- a/mysql-test/t/rpl_view.test +++ b/mysql-test/t/rpl_view.test @@ -152,4 +152,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 diff --git a/sql/sql_view.cc b/sql/sql_view.cc index bf48cd0094a..46ff04702fd 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -692,6 +692,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, char dir_buff[FN_REFLEN], path_buff[FN_REFLEN]; const char *endp; LEX_STRING dir, file, path; + int error= 0; DBUG_ENTER("mysql_register_view"); /* print query */ @@ -702,77 +703,11 @@ 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())); - /* print file name */ - dir.length= build_table_filename(dir_buff, sizeof(dir_buff), - view->db, "", "", 0); - dir.str= dir_buff; - - path.length= build_table_filename(path_buff, sizeof(path_buff), - view->db, view->table_name, reg_ext, 0); - path.str= path_buff; - - file.str= path.str + dir.length; - file.length= path.length - dir.length; - - /* init timestamp */ - if (!view->timestamp.str) - view->timestamp.str= view->timestamp_buffer; - - /* check old .frm */ - { - char path_buff[FN_REFLEN]; - LEX_STRING path; - File_parser *parser; - - path.str= path_buff; - fn_format(path_buff, file.str, dir.str, "", MY_UNPACK_FILENAME); - path.length= strlen(path_buff); - - if (!access(path.str, F_OK)) - { - if (mode == VIEW_CREATE_NEW) - { - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); - DBUG_RETURN(-1); - } - - if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0))) - DBUG_RETURN(1); - - 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); - } - - /* - read revision number - - TODO: read dependence list, too, to process cascade/restrict - TODO: special cascade/restrict procedure for alter? - */ - if (parser->parse((gptr)view, thd->mem_root, - view_parameters + revision_number_position, 1, - &file_parser_dummy_hook)) - { - DBUG_RETURN(thd->net.report_error? -1 : 0); - } - } - else - { - 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->query.str= str.c_ptr(); + view->query.length= str.length(); view->source.str= thd->query + thd->lex->create_view_select_start; endp= view->source.str; endp= skip_rear_comments(endp, thd->query + thd->query_length); @@ -818,6 +753,78 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, } } loop_out: + /* print file name */ + dir.length= build_table_filename(dir_buff, sizeof(dir_buff), + view->db, "", "", 0); + dir.str= dir_buff; + + path.length= build_table_filename(path_buff, sizeof(path_buff), + view->db, view->table_name, reg_ext, 0); + path.str= path_buff; + + file.str= path.str + dir.length; + file.length= path.length - dir.length; + + /* init timestamp */ + if (!view->timestamp.str) + view->timestamp.str= view->timestamp_buffer; + + /* check old .frm */ + { + char path_buff[FN_REFLEN]; + LEX_STRING path; + File_parser *parser; + + path.str= path_buff; + fn_format(path_buff, file.str, dir.str, "", MY_UNPACK_FILENAME); + path.length= strlen(path_buff); + + if (!access(path.str, F_OK)) + { + if (mode == VIEW_CREATE_NEW) + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); + error= -1; + goto err; + } + + if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0))) + { + 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"); + error= -1; + goto err; + } + + /* + read revision number + + TODO: read dependence list, too, to process cascade/restrict + TODO: special cascade/restrict procedure for alter? + */ + if (parser->parse((gptr)view, thd->mem_root, + view_parameters + revision_number_position, 1, + &file_parser_dummy_hook)) + { + error= thd->net.report_error? -1 : 0; + goto err; + } + } + else + { + if (mode == VIEW_ALTER) + { + my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias); + error= -1; + goto err; + } + } + } /* Check that table of main select do not used in subqueries. @@ -842,15 +849,23 @@ loop_out: !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= 0; + DBUG_RETURN(error); }