mariadb/sql/sql_delete.cc
unknown d61418b94f Portability fixes.
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
2001-08-21 20:06:00 +03:00

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);
}