summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <georg@lmy002.wdf.sap.corp>2005-09-16 17:13:21 +0200
committerunknown <georg@lmy002.wdf.sap.corp>2005-09-16 17:13:21 +0200
commitbf58b698e22efe0849fc8ee18fc30e3914d73409 (patch)
tree42699dfbd0ad93df462e371d7a4a287bd38af876
parentb34d5bd24733e2e50d4d32c37fa9ebc722177bf2 (diff)
downloadmariadb-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.result9
-rw-r--r--mysql-test/t/view.test13
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sql_rename.cc34
-rw-r--r--sql/sql_view.cc100
-rw-r--r--sql/sql_view.h1
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)