Commit 48ee575e authored by monty@donna.mysql.com's avatar monty@donna.mysql.com
Browse files

Merge of last changes

parent d79b0cc9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
2000-08-21  Michael Widenius  <monty@mysql.com>

* Added RENAME TABLE.

2000-08-20  Michael Widenius  <monty@mysql.com>

* Added memory as inline functions to THD to get them a bit faster
+12 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags);
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
int quick_rm_table(enum db_type base,const char *db,
		   const char *table_name);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length);
void mysql_init_select(LEX *lex);
@@ -293,6 +294,11 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
		      List<Alter_column> &alter_list,
		      bool drop_primary,
		      enum enum_duplicates handle_duplicates);
bool mysql_rename_table(enum db_type base,
			const char *old_db,
			const char * old_name,
			const char *new_db,
			const char * new_name);
bool close_cached_table(THD *thd,TABLE *table);
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
@@ -316,6 +322,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
void close_old_data_files(THD *thd, TABLE *table, bool abort_locks);
bool close_data_tables(THD *thd,const char *db, const char *table_name);
bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables);
@@ -488,6 +495,11 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);

/* Lock based on name */
int lock_table_name(THD *thd, TABLE_LIST *table_list);
void unlock_table_name(THD *thd, TABLE_LIST *table_list);
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);

extern int flush_master_info(MASTER_INFO* mi);

/* old unireg functions */
+60 −59
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ extern "C" int gethostname(char *name, int namelen);
#endif

static bool check_table_access(THD *thd,uint want_access,TABLE_LIST *tables);
static bool check_lock_tables(THD *thd,TABLE_LIST *tables);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_dup(THD *thd,const char *db,const char *name,
		      TABLE_LIST *tables);
static void mysql_init_query(THD *thd);
@@ -387,7 +387,6 @@ pthread_handler_decl(handle_one_connection,arg)
      goto end_thread;
    }

    thd->alloc.free=thd->alloc.used=0;
    if (thd->max_join_size == HA_POS_ERROR)
      thd->options |= OPTION_BIG_SELECTS;
    if (thd->client_capabilities & CLIENT_COMPRESS)
@@ -395,7 +394,7 @@ pthread_handler_decl(handle_one_connection,arg)
    if (thd->options & OPTION_ANSI_MODE)
      thd->client_capabilities|=CLIENT_IGNORE_SPACE;

    thd->proc_info=0;
    thd->proc_info=0;				// Remove 'login'
    thd->version=refresh_version;
    thd->set_time();
    while (!net->error && net->vio != 0 && !thd->killed)
@@ -436,7 +435,7 @@ int handle_bootstrap(THD *thd,FILE *file)

  if (init_thr_lock() ||
      my_pthread_setspecific_ptr(THR_THD,  thd) ||
      my_pthread_setspecific_ptr(THR_MALLOC, &thd->alloc) ||
      my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root) ||
      my_pthread_setspecific_ptr(THR_NET,  &thd->net))
  {
    close_connection(&thd->net,ER_OUT_OF_RESOURCES);
@@ -450,7 +449,6 @@ int handle_bootstrap(THD *thd,FILE *file)
  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
#endif

  thd->alloc.free=thd->alloc.used=0;
  if (thd->max_join_size == (ulong) ~0L)
    thd->options |= OPTION_BIG_SELECTS;

@@ -464,9 +462,9 @@ int handle_bootstrap(THD *thd,FILE *file)
    while (length && (isspace(buff[length-1]) || buff[length-1] == ';'))
      length--;
    buff[length]=0;
    init_sql_alloc(&thd->alloc,8192);
    init_sql_alloc(&thd->mem_root,8192);
    thd->current_tablenr=0;
    thd->query= sql_memdup(buff,length+1);
    thd->query= thd->memdup(buff,length+1);
    thd->query_id=query_id++;
    mysql_parse(thd,thd->query,length);
    close_thread_tables(thd);			// Free tables
@@ -474,7 +472,7 @@ int handle_bootstrap(THD *thd,FILE *file)
    {
      DBUG_RETURN(-1);
    }
    free_root(&thd->alloc);
    free_root(&thd->mem_root);
  }
  DBUG_RETURN(0);
}
@@ -542,7 +540,7 @@ bool do_command(THD *thd)
  enum enum_server_command command;
  DBUG_ENTER("do_command");

  init_sql_alloc(&thd->alloc,8192);
  init_sql_alloc(&thd->mem_root,8192);
  net= &thd->net;
  thd->current_tablenr=0;

@@ -642,7 +640,7 @@ bool do_command(THD *thd)
      packet_length--;
    }
    *pos=0;
    if (!(thd->query= (char*) sql_memdup((gptr) (packet+1),packet_length)))
    if (!(thd->query= (char*) thd->memdup((gptr) (packet+1),packet_length)))
      break;
    thd->packet.shrink(net_buffer_length);	// Reclaim some memory
    if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -670,8 +668,8 @@ bool do_command(THD *thd)
      break;
    }
    thd->free_list=0;
    table_list.name=table_list.real_name=sql_strdup(packet+1);
    thd->query=fields=sql_strdup(strend(packet+1)+1);
    table_list.name=table_list.real_name=thd->strdup(packet+1);
    thd->query=fields=thd->strdup(strend(packet+1)+1);
    mysql_log.write(command,"%s %s",table_list.real_name,fields);
    remove_escape(table_list.real_name);	// This can't have wildcards

@@ -693,7 +691,7 @@ bool do_command(THD *thd)

  case COM_CREATE_DB:
    {
      char *db=sql_strdup(packet+1);
      char *db=thd->strdup(packet+1);
      if (check_access(thd,CREATE_ACL,db,0,1))
	break;
      mysql_log.write(command,packet+1);
@@ -702,7 +700,7 @@ bool do_command(THD *thd)
    }
  case COM_DROP_DB:
    {
      char *db=sql_strdup(packet+1);
      char *db=thd->strdup(packet+1);
      if (check_access(thd,DROP_ACL,db,0,1))
	break;
      mysql_log.write(command,db);
@@ -719,7 +717,7 @@ bool do_command(THD *thd)
      ushort flags;
      pos = uint4korr(packet + 1);
      flags = uint2korr(packet + 5);
      mysql_binlog_send(thd, sql_strdup(packet + 7), pos, flags);
      mysql_binlog_send(thd, thd->strdup(packet + 7), pos, flags);
      break;
    }
  case COM_REFRESH:
@@ -746,7 +744,7 @@ bool do_command(THD *thd)
    send_eof(net);				// This is for 'quit request'
    close_connection(net);
    close_thread_tables(thd);			// Free before kill
    free_root(&thd->alloc);
    free_root(&thd->mem_root);
    kill_mysql();
    error=TRUE;
    break;
@@ -827,7 +825,7 @@ bool do_command(THD *thd)
  thread_running--;
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
  thd->packet.shrink(net_buffer_length);	// Reclaim some memory
  free_root(&thd->alloc);
  free_root(&thd->mem_root);
  DBUG_RETURN(error);
}

@@ -1132,51 +1130,49 @@ mysql_execute_command(void)
      break;
    }
#endif
  case SQLCOM_RENAME_TABLE:
    if (check_db_used(thd,tables) ||
	check_table_access(thd,ALTER_ACL,tables))
      goto error;
    if (mysql_rename_tables(thd,tables))
      res= -1;
    break;
  case SQLCOM_SHOW_CREATE:
#ifdef DONT_ALLOW_SHOW_COMMANDS
    send_error(&thd->net,ER_NOT_ALLOWED_COMMAND);	/* purecov: inspected */
    DBUG_VOID_RETURN;
#else
    {
      if(! tables->db)
	tables->db = thd->db;
      if (!tables->db)
	{
	  send_error(&thd->net,ER_NO_DB_ERROR);	/* purecov: inspected */
	  goto error;				/* purecov: inspected */
	}
      if (check_db_used(thd, tables) ||
	  check_access(thd, SELECT_ACL | EXTRA_ACL, tables->db,
		       &tables->grant.privilege))
	goto error;
      res = mysqld_show_create(thd, tables);  
      break;
    }
#endif
  case SQLCOM_REPAIR:
    {
      if (!tables->db)
        tables->db=thd->db;
      if (check_access(thd,SELECT_ACL | INSERT_ACL,tables->db,
		     &tables->grant.privilege))
      if (check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
	goto error; /* purecov: inspected */
      if (grant_option && check_grant(thd,SELECT_ACL | INSERT_ACL,tables))
        goto error;
      res = mysql_repair_table(thd, tables, &lex->check_opt);
      break;
    }
  case SQLCOM_CHECK:
    {
      if (!tables->db)
        tables->db=thd->db;
      if (check_access(thd,SELECT_ACL,tables->db,
		     &tables->grant.privilege))
      if (check_db_used(thd,tables) ||
	  check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables))
	goto error; /* purecov: inspected */
      if (grant_option && check_grant(thd,SELECT_ACL,tables))
        goto error;
      res = mysql_check_table(thd, tables, &lex->check_opt);
      break;
    }
  case SQLCOM_ANALYZE:
  {
    if (!tables->db)
      tables->db=thd->db;
    if (check_access(thd,SELECT_ACL|INSERT_ACL,tables->db,
		     &tables->grant.privilege))
    if (check_db_used(thd,tables) ||
	check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
      goto error; /* purecov: inspected */
    if (grant_option && check_grant(thd,SELECT_ACL|INSERT_ACL,tables))
      goto error;
    res = mysql_analyze_table(thd, tables);
    break;
  }
@@ -1515,7 +1511,7 @@ mysql_execute_command(void)
      thd->locked_tables=0;			// Will be automaticly closed
      close_thread_tables(thd);
    }
    if (check_lock_tables(thd,tables))
    if (check_db_used(thd,tables))
      goto error;
    thd->in_lock_tables=1;
    if (!(res=open_and_lock_tables(thd,tables)))
@@ -1749,7 +1745,7 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
  {
    if ((thd->master_access & want_access) == want_access && thd->db)
      tables->grant.privilege= want_access;
    else if (tables->db)
    else if (tables->db && tables->db == thd->db)
    {
      if (found && !grant_option)		// db already checked
	tables->grant.privilege=found_access;
@@ -1758,6 +1754,7 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
	if (check_access(thd,want_access,tables->db,&tables->grant.privilege))
	  return TRUE;				// Access denied
	found_access=tables->grant.privilege;
	found=1;
      }
    }
    else if (check_access(thd,want_access,tables->db,&tables->grant.privilege))
@@ -1769,7 +1766,7 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
}


static bool check_lock_tables(THD *thd,TABLE_LIST *tables)
static bool check_db_used(THD *thd,TABLE_LIST *tables)
{
  for (; tables ; tables=tables->next)
  {
@@ -2274,21 +2271,24 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
  if (lower_case_table_names)
    casedn_str(table->table.str);
#endif
  if (!(ptr = (TABLE_LIST *) sql_calloc(sizeof(TABLE_LIST))))
  if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
    DBUG_RETURN(0);				/* purecov: inspected */
  ptr->db= table->db.str;
  ptr->real_name=table->table.str;
  ptr->name=alias_str;
  ptr->lock_type=flags;
  if (use_index)
    ptr->use_index=(List<String> *) sql_memdup((gptr) use_index,
    ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
					       sizeof(*use_index));
  if (ignore_index)
    ptr->ignore_index=(List<String> *) sql_memdup((gptr) ignore_index,
    ptr->ignore_index=(List<String> *) thd->memdup((gptr) ignore_index,
						   sizeof(*ignore_index));

  /* check that used name is unique */
  current_db=thd->db ? thd->db : "";

  if (flags != TL_IGNORE)
  {
    for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.table_list.first ; tables ;
	 tables=tables->next)
    {
@@ -2300,6 +2300,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
	DBUG_RETURN(0);				/* purecov: tested */
      }
    }
  }
  link_in_list(&thd->lex.table_list,(byte*) ptr,(byte**) &ptr->next);
  DBUG_RETURN(ptr);
}

sql/sql_rename.cc

0 → 100644
+132 −0
Original line number Diff line number Diff line
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/*
  Atomic rename of table;  RENAME TABLE t1 to t2, tmp to t1 [,...]
*/

#include "mysql_priv.h"


static TABLE_LIST *mysql_rename_tables(THD *thd, TABLE_LIST *table_list,
				       bool skip_error);

/*
  Every second entry in the table_list is the original name and every
  second entry is the new name.
*/

bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
{
  bool error=1,got_all_locks=1;
  db_type table_type;
  TABLE_LIST *lock_table,*ren_table=0,*new_table;
  DBUG_ENTER("mysql_rename_tables");
  
  /* Avoid problems with a rename on a table that we have locked or
     if the user is trying to to do this in a transcation context */

  if (thd->locked_tables || thd->active_transaction())
  {
    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION,MYF(0));
    DBUG_RETURN(1);
  }
      
  VOID(pthread_mutex_lock(&LOCK_open));
  for (lock_table=table_list ; lock_table ; lock_table=lock_table->next)
  {
    int got_lock;
    if ((got_lock=lock_table_name(thd,lock_table)) < 0)
      goto end;
    if (got_lock)
      got_all_locks=0;
  }
  
  if (!got_all_locks && wait_for_locked_table_names(thd,table_list))
    goto end;

  if (!(ren_table=mysql_rename_tables(thd,table_list,0)))
    error=0;
  
end:
  if (ren_table)
  {
    /* Rename didn't succeed;  rename back the tables in reverse order */
    TABLE_LIST *prev=0,*table;
    /*
      Reverse the table list ; Note that we need to handle the case that
      every second entry must stay in place in respect to the previous
    */
    while (table_list)
    {
      TABLE_LIST *next=table_list->next->next;
      table_list->next->next=prev;
      prev=table_list;
      table_list=next;
    }
    table_list=prev;

    /* Find the last renamed table */
    for (table=table_list ; table->next != ren_table ;
	 table=table->next->next) ;
    table=table->next->next;			// Skipp error table
    /* Revert to old names */
    mysql_rename_tables(thd, table, 1);
    /* Note that lock_table == 0 here, so the unlock loop will work */
  }
  if (!error)
  {
    mysql_update_log.write(thd->query,thd->query_length);
    Query_log_event qinfo(thd, thd->query);
    mysql_bin_log.write(&qinfo);
  }
  for (TABLE_LIST *table=table_list ; table != lock_table ; table=table->next)
    unlock_table_name(thd,table);
  pthread_cond_broadcast(&COND_refresh);
  pthread_mutex_unlock(&LOCK_open);
  DBUG_RETURN(error);
}


/*
  Rename all tables in list; Return pointer to wrong entry if something goes
  wrong.
*/

static TABLE_LIST *
mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
{
  TABLE_LIST *ren_table;
  for (ren_table=table_list ; ren_table ; ren_table=ren_table->next)
  {
    db_type table_type;
    char name[FN_REFLEN];
    TABLE_LIST *new_table=ren_table->next;

    sprintf(name,"%s/%s/%s%s",mysql_data_home,
	    ren_table->db,ren_table->name,
	    reg_ext);
    if ((table_type=get_table_type(name)) == DB_TYPE_UNKNOWN ||
	mysql_rename_table(table_type,
			   ren_table->db, ren_table->name,
			   new_table->db, new_table->name))
    {
      if (!skip_error)
	return ren_table;
    }
  }
  return 0;
}