diff options
author | unknown <georg@lmy002.wdf.sap.corp> | 2005-09-16 17:13:21 +0200 |
---|---|---|
committer | unknown <georg@lmy002.wdf.sap.corp> | 2005-09-16 17:13:21 +0200 |
commit | bf58b698e22efe0849fc8ee18fc30e3914d73409 (patch) | |
tree | 42699dfbd0ad93df462e371d7a4a287bd38af876 | |
parent | b34d5bd24733e2e50d4d32c37fa9ebc722177bf2 (diff) | |
download | mariadb-git-bf58b698e22efe0849fc8ee18fc30e3914d73409.tar.gz |
Fix for bug#5508 after Sanja's review
mysql-test/r/view.result:
test results for rename table view1 to view2
mysql-test/t/view.test:
tests for rename table view1 to view2
sql/share/errmsg.txt:
added new errormessage (schema change not allowed in rename table view)
sql/sql_rename.cc:
added support for renaming views
sql/sql_view.cc:
added new function mysql_rename_view
sql/sql_view.h:
added prototype mysql_rename_view
-rw-r--r-- | mysql-test/r/view.result | 9 | ||||
-rw-r--r-- | mysql-test/t/view.test | 13 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 2 | ||||
-rw-r--r-- | sql/sql_rename.cc | 34 | ||||
-rw-r--r-- | sql/sql_view.cc | 100 | ||||
-rw-r--r-- | sql/sql_view.h | 1 |
6 files changed, 150 insertions, 9 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 4cb3db2e4aa..b4451a670d2 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -845,6 +845,15 @@ select * from v1; cast(1 as char(3)) 1 drop view v1; +create table t1 (a int); +create view v1 as select a from t1; +create database seconddb; +rename table v1 to seconddb.v1; +ERROR HY000: Changing schema from 'test' to 'seconddb' is not allowed. +rename table v1 to v2; +drop table t1; +drop view v2; +drop database seconddb; create view v1 as select 'a',1; create view v2 as select * from v1 union all select * from v1; create view v3 as select * from v2 where 1 = (select `1` from v2); diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 0e3a7b8aeac..b9c300132cf 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -786,6 +786,19 @@ select * from v1; drop view v1; # +# renaming views +# +create table t1 (a int); +create view v1 as select a from t1; +create database seconddb; +-- error 1450 +rename table v1 to seconddb.v1; +rename table v1 to v2; +drop table t1; +drop view v2; +drop database seconddb; + +# # bug handling from VIEWs # create view v1 as select 'a',1; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 9f6bc72ab81..09589c98dce 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5413,3 +5413,5 @@ ER_VIEW_OTHER_USER eng "You need the SUPER privilege for creation view with %-.64s@%-.64s definer" ER_NO_SUCH_USER eng "There is not %-.64s@%-.64s registered" +ER_FORBID_SCHEMA_CHANGE + eng "Changing schema from '%-.64s' to '%-.64s' is not allowed." diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 3880aa428b9..b848809ccc9 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -133,6 +133,7 @@ static TABLE_LIST * rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) { TABLE_LIST *ren_table,*new_table; + frm_type_enum frm_type; DBUG_ENTER("rename_tables"); for (ren_table= table_list; ren_table; ren_table= new_table->next_local) @@ -164,18 +165,35 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) ren_table->db, old_alias, reg_ext); unpack_filename(name, name); - if ((table_type=get_table_type(thd, name)) == DB_TYPE_UNKNOWN) + if ((frm_type= mysql_frm_type(name)) == FRMTYPE_TABLE && + (table_type= get_table_type(thd, name)) == DB_TYPE_UNKNOWN) { my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno); if (!skip_error) - DBUG_RETURN(ren_table); + DBUG_RETURN(ren_table); } - else if (mysql_rename_table(table_type, - ren_table->db, old_alias, - new_table->db, new_alias)) - { - if (!skip_error) - DBUG_RETURN(ren_table); + else { + int rc= 1; + switch (frm_type) + { + case FRMTYPE_TABLE: + rc= mysql_rename_table(table_type, ren_table->db, old_alias, + new_table->db, new_alias); + break; + case FRMTYPE_VIEW: + /* change of schema is not allowed */ + if (strcmp(ren_table->db, new_table->db)) + my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db, + new_table->db); + else + rc= mysql_rename_view(thd, new_alias, ren_table); + break; + case FRMTYPE_ERROR: + default: + my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno); + } + if (rc && !skip_error) + DBUG_RETURN(ren_table); } } DBUG_RETURN(0); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 5155e605ce0..2e4e9c54b01 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -479,8 +479,12 @@ err: /* index of revision number in following table */ static const int revision_number_position= 8; +/* index of source */ +static const int source_number_position= 11; /* index of last required parameter for making view */ static const int required_view_parameters= 10; +/* number of backups */ +static const int num_view_backups= 3; /* table of VIEW .frm field descriptors @@ -708,7 +712,7 @@ loop_out: } if (sql_create_definition_file(&dir, &file, view_file_type, - (gptr)view, view_parameters, 3)) + (gptr)view, view_parameters, num_view_backups)) { DBUG_RETURN(thd->net.report_error? -1 : 1); } @@ -1367,3 +1371,97 @@ int view_checksum(THD *thd, TABLE_LIST *view) HA_ADMIN_WRONG_CHECKSUM : HA_ADMIN_OK); } + +bool rename_view_files(const char *schema, const char *old_name, + const char *new_name, ulonglong revision) +{ + char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN]; + + strxnmov(old_path, FN_REFLEN, mysql_data_home, "/", schema, "/", + old_name, reg_ext, NullS); + (void) unpack_filename(old_path, old_path); + + strxnmov(new_path, FN_REFLEN, mysql_data_home, "/", schema, "/", + new_name, reg_ext, NullS); + (void) unpack_filename(new_path, new_path); + + if (my_rename(old_path, new_path, MYF(MY_WME))) + return 1; + + /* check if arc_dir exists */ + strxnmov(arc_path, FN_REFLEN, mysql_data_home, "/", schema, "/arc", NullS); + (void) unpack_filename(arc_path, arc_path); + + if (revision && !access(arc_path, F_OK)) + { + while (revision) { + my_snprintf(old_path, FN_REFLEN, "%s/%s%s-%04lu", + arc_path, old_name, reg_ext, (ulong)revision); + (void) unpack_filename(old_path, old_path); + my_snprintf(new_path, FN_REFLEN, "%s/%s%s-%04lu", + arc_path, new_name, reg_ext, (ulong)revision); + (void) unpack_filename(new_path, new_path); + if (my_rename(old_path, new_path, MYF(0))) + return 0; + revision--; + } + } + return 0; +} + +bool +mysql_rename_view(THD *thd, + const char *new_name, + TABLE_LIST *view) +{ + LEX_STRING pathstr, file; + File_parser *parser; + char view_path[FN_REFLEN]; + + DBUG_ENTER("mysql_rename_view"); + + strxnmov(view_path, FN_REFLEN, mysql_data_home, "/", view->db, "/", + view->table_name, reg_ext, NullS); + (void) unpack_filename(view_path, view_path); + + pathstr.str= (char *)view_path; + pathstr.length= strlen(view_path); + + if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) && + is_equal(&view_type, parser->type())) { + char dir_buff[FN_REFLEN], file_buff[FN_REFLEN]; + + /* get view definition and source */ + if (mysql_make_view(parser, view) || + parser->parse((gptr)view, thd->mem_root, + view_parameters + source_number_position, 1)) + DBUG_RETURN(1); + + /* rename view and it's backups */ + if (rename_view_files(view->db, view->table_name, new_name, view->revision - 1)) + DBUG_RETURN(1); + + strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", view->db, "/", NullS); + (void) unpack_filename(dir_buff, dir_buff); + + pathstr.str= (char*)dir_buff; + pathstr.length= strlen(dir_buff); + + file.str= file_buff; + file.length= (strxnmov(file_buff, FN_REFLEN, new_name, reg_ext, NullS) + - file_buff); + + if (sql_create_definition_file(&pathstr, &file, view_file_type, + (gptr)view, view_parameters, num_view_backups)) { + /* restore renamed view in case of error */ + rename_view_files(view->db, new_name, view->table_name, view->revision - 1); + DBUG_RETURN(1); + } + } else + DBUG_RETURN(1); + + /* remove cache entries */ + query_cache_invalidate3(thd, view, 0); + sp_cache_invalidate(); + DBUG_RETURN(0); +} diff --git a/sql/sql_view.h b/sql/sql_view.h index 9d961feb143..4cc9eb454fb 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -34,6 +34,7 @@ int view_checksum(THD *thd, TABLE_LIST *view); extern TYPELIB updatable_views_with_limit_typelib; bool check_duplicate_names(List<Item>& item_list, bool gen_unique_view_names); +bool mysql_rename_view(THD *thd, const char *new_name, TABLE_LIST *view); #define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL) |