sql_delete.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:7k
- /* 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 */
- /* Delete of records */
- #include "mysql_priv.h"
- #include "ha_innobase.h"
- /*
- Optimize delete of all rows by doing a full generate of the table
- This will work even if the .ISM and .ISD tables are destroyed
- */
- int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table)
- {
- char path[FN_REFLEN];
- int error;
- TABLE **table_ptr;
- DBUG_ENTER("generate_table");
- thd->proc_info="generate_table";
- if (global_read_lock)
- {
- if(thd->global_read_lock)
- {
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
- table_list->real_name);
- DBUG_RETURN(-1);
- }
- pthread_mutex_lock(&LOCK_open);
- while (global_read_lock && ! thd->killed ||
- thd->version != refresh_version)
- {
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- }
- pthread_mutex_unlock(&LOCK_open);
- }
-
- /* If it is a temporary table, close and regenerate it */
- if ((table_ptr=find_temporary_table(thd,table_list->db,
- table_list->real_name)))
- {
- TABLE *table= *table_ptr;
- HA_CREATE_INFO create_info;
- table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
- bzero((char*) &create_info,sizeof(create_info));
- create_info.auto_increment_value= table->file->auto_increment_value;
- db_type table_type=table->db_type;
- strmov(path,table->path);
- *table_ptr= table->next; // Unlink table from list
- close_temporary(table,0);
- *fn_ext(path)=0; // Remove the .frm extension
- ha_create_table(path, &create_info,1);
- if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
- table_list->real_name, 1))))
- {
- (void) rm_temporary_table(table_type, path);
- }
- }
- else
- {
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
- table_list->real_name,reg_ext);
- fn_format(path,path,"","",4);
- VOID(pthread_mutex_lock(&LOCK_open));
- if (locked_table)
- mysql_lock_abort(thd,locked_table); // end threads waiting on lock
- // close all copies in use
- if (remove_table_from_cache(thd,table_list->db,table_list->real_name))
- {
- if (!locked_table)
- {
- VOID(pthread_mutex_unlock(&LOCK_open));
- DBUG_RETURN(1); // We must get a lock on table
- }
- }
- if (locked_table)
- locked_table->file->extra(HA_EXTRA_FORCE_REOPEN);
- if (thd->locked_tables)
- close_data_tables(thd,table_list->db,table_list->real_name);
- else
- close_thread_tables(thd,1);
- HA_CREATE_INFO create_info;
- bzero((char*) &create_info,sizeof(create_info));
- *fn_ext(path)=0; // Remove the .frm extension
- error= ha_create_table(path,&create_info,1) ? -1 : 0;
- if (thd->locked_tables && reopen_tables(thd,1,0))
- error= -1;
- VOID(pthread_mutex_unlock(&LOCK_open));
- }
- if (!error)
- {
- mysql_update_log.write(thd,thd->query,thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query);
- mysql_bin_log.write(&qinfo);
- }
- send_ok(&thd->net); // This should return record count
- }
- DBUG_RETURN(error ? -1 : 0);
- }
- int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
- thr_lock_type lock_type, ulong options)
- {
- int error;
- TABLE *table;
- SQL_SELECT *select;
- READ_RECORD info;
- bool using_limit=limit != HA_POS_ERROR;
- bool use_generate_table,using_transactions;
- DBUG_ENTER("mysql_delete");
- if (!table_list->db)
- table_list->db=thd->db;
- if ((thd->options & OPTION_SAFE_UPDATES) && !conds)
- {
- send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
- }
- use_generate_table= (!using_limit && !conds &&
- !(specialflag &
- (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
- !(thd->options &
- (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)));
- #ifdef HAVE_INNOBASE_DB
- /* We need to add code to not generate table based on the table type */
- if (!innobase_skip)
- use_generate_table=0; // Innobase can't use re-generate table
- #endif
- if (use_generate_table && ! thd->open_tables)
- {
- error=generate_table(thd,table_list,(TABLE*) 0);
- if (error <= 0)
- DBUG_RETURN(error); // Error or ok
- }
- if (!(table = open_ltable(thd,table_list,
- limit != HA_POS_ERROR ? TL_WRITE_LOW_PRIORITY :
- lock_type)))
- DBUG_RETURN(-1);
- table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
- thd->proc_info="init";
- if (use_generate_table)
- DBUG_RETURN(generate_table(thd,table_list,table));
- table->map=1;
- if (setup_conds(thd,table_list,&conds))
- DBUG_RETURN(-1);
- table->used_keys=table->quick_keys=0; // Can't use 'only index'
- select=make_select(table,0,0,conds,&error);
- if (error)
- DBUG_RETURN(-1);
- if (select && select->check_quick(test(thd->options & SQL_SAFE_UPDATES),
- limit))
- {
- delete select;
- send_ok(&thd->net,0L);
- DBUG_RETURN(0);
- }
- /* If running in safe sql mode, don't allow updates without keys */
- if (!table->quick_keys)
- {
- thd->lex.options|=QUERY_NO_INDEX_USED;
- if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
- {
- delete select;
- send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
- }
- }
- (void) table->file->extra(HA_EXTRA_NO_READCHECK);
- if (options & OPTION_QUICK)
- (void) table->file->extra(HA_EXTRA_QUICK);
- init_read_record(&info,thd,table,select,-1,1);
- ulong deleted=0L;
- thd->proc_info="updating";
- while (!(error=info.read_record(&info)) && !thd->killed)
- {
- if (!(select && select->skipp_record()))
- {
- if (!(error=table->file->delete_row(table->record[0])))
- {
- deleted++;
- if (!--limit && using_limit)
- {
- error= -1;
- break;
- }
- }
- else
- {
- table->file->print_error(error,MYF(0));
- error=0;
- break;
- }
- }
- }
- thd->proc_info="end";
- end_read_record(&info);
- (void) table->file->extra(HA_EXTRA_READCHECK);
- if (options & OPTION_QUICK)
- (void) table->file->extra(HA_EXTRA_NORMAL);
- using_transactions=table->file->has_transactions();
- if (deleted && (error <= 0 || !using_transactions))
- {
- mysql_update_log.write(thd,thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
- error=1;
- }
- if (!using_transactions)
- thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
- }
- if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0))
- error=1;
- if (thd->lock)
- {
- mysql_unlock_tables(thd, thd->lock);
- thd->lock=0;
- }
- delete select;
- if (error >= 0) // Fatal error
- send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0);
- else
- {
- send_ok(&thd->net,deleted);
- DBUG_PRINT("info",("%d records deleted",deleted));
- }
- DBUG_RETURN(0);
- }