Bug #40021: Renaming view fails, archived .frm for view is

missing after downgrade

Obsolete arc/ directory and view .frm file backup support
has been removed by the patch for bug 17823. However, that
bugfix caused a problem with "live downgrades" of the
server: if we rename some view 4 times under 5.1.29/5.0.72
and then try to rename it under 5.1.28/5.0.70 on the same
database, the server fails with a error:

  query 'RENAME TABLE ... TO ...' failed: 6: Error on
  delete of '....frm-0001' (Errcode: 2)

Also .frm file of that view may be lost (renamed to .frm~).

The server failed because it tried to rename latest 3
backup .frm files renaming the view: the server used an
integer value of the "revision" field of .frm file to
extract those file names. After the fix for bug 17823 those
files were not created/maintained any more, however the
"revision" field was incremented as usual. So, the server
failed renaming non existent files.

This fix solves the problem by removing the support for
"revision" .frm file field:
1. New server silently ignores existent "revision" fields
   in old .frm files and never write it down;
2. Old server assumes, that missing "revision" field in new
   .frm files means default value of 0.
3. Accordingly to the fix for bug 17823 the new server
   drops arc/ directory on alter/rename view, so after
   "live downgrade" old server begins maintenance of the
   arc/ directory from scratch without conflicts with .frm
   files.


sql/parse_file.cc:
  Bug #40021: Renaming view fails, archived .frm for view is
              missing after downgrade
  
  1. static write_parameter(): the old_version parameter
     and the section for FILE_OPTIONS_REV have been re moved.
  2. write_parameter(): the max_versions parameter has been
     removed;
  3. sql_create_definition_file(): removal of dead code;
  4. rename_in_schema_file(): revision and num_view_backups
     parameters and dead code have been removed;
  5. File_parser::parse(): FILE_OPTIONS_REV section has been
     removed.
sql/parse_file.h:
  Bug #40021: Renaming view fails, archived .frm for view is
              missing after downgrade
  
  1. The FILE_OPTIONS_REV constant has been removed.
  2. sql_create_definition_file and rename_in_schema_file
     functions: obsolete versions, revision and
     num_view_backups parameters have been removed.
sql/sql_db.cc:
  Bug #40021: Renaming view fails, archived .frm for view is
              missing after downgrade
  
  Commentary update.
sql/sql_trigger.cc:
  Bug #40021: Renaming view fails, archived .frm for view is
              missing after downgrade
  
  sql_create_definition_file() calls have been updates to
  new parameter lists.
sql/sql_view.cc:
  Bug #40021: Renaming view fails, archived .frm for view is
              missing after downgrade
  
  1. The mysql_create_view function code is used for both
     CREATE VIEW and ALTER queries, but query cache is
     necessary for ALTER command only. Check for a non first
     view revision has been replaced with a direct check for
     ALTER query.
  2. The num_view_backups global constant has been removed.
  3. view_parameters: the "revision" .frm field support has
     been removed.
  4. sql_create_definition_file and rename_in_schema_file
     function calls have been updates to new parameter lists.
sql/table.h:
  Bug #40021: Renaming view fails, archived .frm for view is
              missing after downgrade
  
  TABLE_LIST: the revision field has been removed.
This commit is contained in:
Gleb Shchepa 2008-11-14 21:25:57 +04:00
commit 56b9586fd1
6 changed files with 17 additions and 126 deletions

View file

@ -88,7 +88,6 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s)
file pointer to IO_CACHE structure for writing
base pointer to data structure
parameter pointer to parameter descriptor
old_version for returning back old version number value
RETURN
FALSE - OK
@ -96,8 +95,7 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s)
*/
static my_bool
write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
ulonglong *old_version)
write_parameter(IO_CACHE *file, gptr base, File_option *parameter)
{
char num_buf[20]; // buffer for numeric operations
// string for numeric operations
@ -125,15 +123,6 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
DBUG_RETURN(TRUE);
break;
}
case FILE_OPTIONS_REV:
{
ulonglong *val_i= (ulonglong *)(base + parameter->offset);
*old_version= (*val_i)++;
num.set(*val_i, &my_charset_bin);
if (my_b_append(file, (const byte *)num.ptr(), num.length()))
DBUG_RETURN(TRUE);
break;
}
case FILE_OPTIONS_TIMESTAMP:
{
/* string have to be allocated already */
@ -205,7 +194,6 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
base base address for parameter reading (structure like
TABLE)
parameters parameters description
max_versions number of versions to save
RETURN
FALSE - OK
@ -215,13 +203,11 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
my_bool
sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
const LEX_STRING *type,
gptr base, File_option *parameters,
uint max_versions)
gptr base, File_option *parameters)
{
File handler;
IO_CACHE file;
char path[FN_REFLEN+1]; // +1 to put temporary file name for sure
ulonglong old_version= ULONGLONG_MAX;
int path_end;
File_option *param;
DBUG_ENTER("sql_create_definition_file");
@ -255,7 +241,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
if (my_b_append(&file, (const byte *)param->name.str,
param->name.length) ||
my_b_append(&file, (const byte *)STRING_WITH_LEN("=")) ||
write_parameter(&file, base, param, &old_version) ||
write_parameter(&file, base, param) ||
my_b_append(&file, (const byte *)STRING_WITH_LEN("\n")))
goto err_w_cache;
}
@ -269,55 +255,6 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
}
path[path_end]='\0';
#ifdef FRM_ARCHIVE
// archive copies management: disabled unused feature (see bug #17823).
if (!access(path, F_OK))
{
if (old_version != ULONGLONG_MAX && max_versions != 0)
{
// save backup
char path_arc[FN_REFLEN];
// backup old version
char path_to[FN_REFLEN];
// check archive directory existence
fn_format(path_arc, "arc", dir->str, "", MY_UNPACK_FILENAME);
if (access(path_arc, F_OK))
{
if (my_mkdir(path_arc, 0777, MYF(MY_WME)))
{
DBUG_RETURN(TRUE);
}
}
my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu",
path_arc, file_name->str, (ulong) old_version);
if (my_rename(path, path_to, MYF(MY_WME)))
{
DBUG_RETURN(TRUE);
}
// remove very old version
if (old_version > max_versions)
{
my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu",
path_arc, file_name->str,
(ulong)(old_version - max_versions));
if (!access(path_arc, F_OK) && my_delete(path_to, MYF(MY_WME)))
{
DBUG_RETURN(TRUE);
}
}
}
else
{
if (my_delete(path, MYF(MY_WME))) // no backups
{
DBUG_RETURN(TRUE);
}
}
}
#endif//FRM_ARCHIVE
{
// rename temporary file
@ -346,8 +283,6 @@ err_w_file:
schema name of given schema
old_name original file name
new_name new file name
revision revision number
num_view_backups number of backups
RETURN
0 - OK
@ -356,8 +291,7 @@ err_w_file:
*/
my_bool rename_in_schema_file(THD *thd,
const char *schema, const char *old_name,
const char *new_name, ulonglong revision,
uint num_view_backups)
const char *new_name)
{
char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN];
@ -376,23 +310,6 @@ my_bool rename_in_schema_file(THD *thd,
strxnmov(arc_path, FN_REFLEN, mysql_data_home, "/", schema, "/arc", NullS);
(void) unpack_filename(arc_path, arc_path);
#ifdef FRM_ARCHIVE
if (revision > 0 && !access(arc_path, F_OK))
{
ulonglong limit= ((revision > num_view_backups) ?
revision - num_view_backups : 0);
for (; revision > limit ; 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);
my_rename(old_path, new_path, MYF(0));
}
}
#else//FRM_ARCHIVE
{ // remove obsolete 'arc' directory and files if any
MY_DIR *new_dirp;
if ((new_dirp = my_dir(arc_path, MYF(MY_DONT_SORT))))
@ -401,7 +318,6 @@ my_bool rename_in_schema_file(THD *thd,
(void) mysql_rm_arc_files(thd, new_dirp, arc_path);
}
}
#endif//FRM_ARCHIVE
return 0;
}
@ -838,7 +754,6 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
break;
}
case FILE_OPTIONS_ULONGLONG:
case FILE_OPTIONS_REV:
if (!(eol= strchr(ptr, '\n')))
{
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),