mirror of
https://github.com/MariaDB/server.git
synced 2025-01-23 23:34:34 +01:00
d61418b94f
Patches required by Gemini Fix to properly detect if there is an active transaction in InnoDB Fix to not lock thread structure when doing automatic rollback when thread ends Allow -O lower_case_names=0 on UNIX Docs/manual.texi: Some updates from mailing list. Changelog client/mysqlbinlog.cc: Removed variables declared in net.c configure.in: Added test for strtoll and fixed test for gethostname_r for AIX mysql-test/t/innodb.test: Added test of active transactions sql/field.cc: Patch required by Gemini sql/field.h: Patch required by Gemini sql/filesort.cc: Patch required by Gemini sql/gen_lex_hash.cc: Update to support new syntax sql/ha_gemini.cc: Patch required by Gemini sql/ha_gemini.h: Patch required by Gemini sql/ha_innobase.cc: Fix to properly detect if there is an active transaction in InnoDB sql/handler.cc: Fix to properly detect if there is an active transaction in InnoDB sql/handler.h: Fix to properly detect if there is an active transaction in InnoDB. Fix for Gemini sql/lex.h: SHOW LOCKS sql/mysqld.cc: Fix to not lock thread structure when doing automatic rollback when thread ends. sql/share/portuguese/errmsg.txt: Update sql/sql_class.cc: Fix to not lock thread structure when doing automatic rollback when thread ends. sql/sql_class.h: Fix to properly detect if there is an active transaction in InnoDB sql/sql_delete.cc: Fix for Gemini sql/sql_parse.cc: Allow -O lower_case_names=0 on UNIX sql/sql_select.cc: Fix for Gemini sql/sql_table.cc: Allow -O lower_case_names=0 on UNIX sql/sql_update.cc: Fix for Gemini sql/sql_yacc.yy: For SHOW LOCKS strings/strto.c: Portability fix
258 lines
7.5 KiB
C++
258 lines
7.5 KiB
C++
/* 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 (!innodb_skip)
|
|
use_generate_table=0; // Innodb 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)) ||
|
|
!limit)
|
|
{
|
|
delete select;
|
|
send_ok(&thd->net,0L);
|
|
DBUG_RETURN(0); // Nothing to delete
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
}
|
|
else
|
|
table->file->unlock_row(); // Row failed selection, release lock on it
|
|
}
|
|
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);
|
|
}
|
|
|
|
|