sql_delete.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /* Delete of records */
  17. #include "mysql_priv.h"
  18. #include "ha_innobase.h"
  19. /*
  20.   Optimize delete of all rows by doing a full generate of the table
  21.   This will work even if the .ISM and .ISD tables are destroyed
  22. */
  23. int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table)
  24. {
  25.   char path[FN_REFLEN];
  26.   int error;
  27.   TABLE **table_ptr;
  28.   DBUG_ENTER("generate_table");
  29.   thd->proc_info="generate_table";
  30.   if (global_read_lock)
  31.   {
  32.     if(thd->global_read_lock)
  33.     {
  34.       my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
  35.        table_list->real_name);
  36.       DBUG_RETURN(-1);
  37.     }
  38.     pthread_mutex_lock(&LOCK_open);
  39.     while (global_read_lock && ! thd->killed ||
  40.    thd->version != refresh_version)
  41.     {
  42.       (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
  43.     }
  44.     pthread_mutex_unlock(&LOCK_open);
  45.   }
  46.   
  47.     /* If it is a temporary table, close and regenerate it */
  48.   if ((table_ptr=find_temporary_table(thd,table_list->db,
  49.       table_list->real_name)))
  50.   {
  51.     TABLE *table= *table_ptr;
  52.     HA_CREATE_INFO create_info;
  53.     table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
  54.     bzero((char*) &create_info,sizeof(create_info));
  55.     create_info.auto_increment_value= table->file->auto_increment_value;
  56.     db_type table_type=table->db_type;
  57.     strmov(path,table->path);
  58.     *table_ptr= table->next; // Unlink table from list
  59.     close_temporary(table,0);
  60.     *fn_ext(path)=0; // Remove the .frm extension
  61.     ha_create_table(path, &create_info,1);
  62.     if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
  63.      table_list->real_name, 1))))
  64.     {
  65.       (void) rm_temporary_table(table_type, path);
  66.     }
  67.   }
  68.   else
  69.   {
  70.     (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
  71.    table_list->real_name,reg_ext);
  72.     fn_format(path,path,"","",4);
  73.     VOID(pthread_mutex_lock(&LOCK_open));
  74.     if (locked_table)
  75.       mysql_lock_abort(thd,locked_table);  // end threads waiting on lock
  76.     // close all copies in use
  77.     if (remove_table_from_cache(thd,table_list->db,table_list->real_name))
  78.     {
  79.       if (!locked_table)
  80.       {
  81. VOID(pthread_mutex_unlock(&LOCK_open));
  82. DBUG_RETURN(1); // We must get a lock on table
  83.       }
  84.     }
  85.     if (locked_table)
  86.       locked_table->file->extra(HA_EXTRA_FORCE_REOPEN);
  87.     if (thd->locked_tables)
  88.       close_data_tables(thd,table_list->db,table_list->real_name);
  89.     else
  90.       close_thread_tables(thd,1);
  91.     HA_CREATE_INFO create_info;
  92.     bzero((char*) &create_info,sizeof(create_info));
  93.     *fn_ext(path)=0; // Remove the .frm extension
  94.     error= ha_create_table(path,&create_info,1) ? -1 : 0;
  95.     if (thd->locked_tables && reopen_tables(thd,1,0))
  96.       error= -1;
  97.     VOID(pthread_mutex_unlock(&LOCK_open));
  98.   }
  99.   if (!error)
  100.   {
  101.     mysql_update_log.write(thd,thd->query,thd->query_length);
  102.     if (mysql_bin_log.is_open())
  103.     {
  104.       Query_log_event qinfo(thd, thd->query);
  105.       mysql_bin_log.write(&qinfo);
  106.     }
  107.     send_ok(&thd->net); // This should return record count
  108.   }
  109.   DBUG_RETURN(error ? -1 : 0);
  110. }
  111. int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
  112.  thr_lock_type lock_type, ulong options)
  113. {
  114.   int error;
  115.   TABLE *table;
  116.   SQL_SELECT *select;
  117.   READ_RECORD info;
  118.   bool  using_limit=limit != HA_POS_ERROR;
  119.   bool         use_generate_table,using_transactions;
  120.   DBUG_ENTER("mysql_delete");
  121.   if (!table_list->db)
  122.     table_list->db=thd->db;
  123.   if ((thd->options & OPTION_SAFE_UPDATES) && !conds)
  124.   {
  125.     send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
  126.     DBUG_RETURN(1);
  127.   }
  128.   use_generate_table= (!using_limit && !conds &&
  129.        !(specialflag &
  130.  (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
  131.        !(thd->options &
  132.  (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)));
  133. #ifdef HAVE_INNOBASE_DB
  134.   /* We need to add code to not generate table based on the table type */
  135.   if (!innobase_skip)
  136.     use_generate_table=0; // Innobase can't use re-generate table
  137. #endif
  138.   if (use_generate_table && ! thd->open_tables)
  139.   {
  140.     error=generate_table(thd,table_list,(TABLE*) 0);
  141.     if (error <= 0)
  142.       DBUG_RETURN(error); // Error or ok
  143.   }
  144.   if (!(table = open_ltable(thd,table_list,
  145.     limit != HA_POS_ERROR ? TL_WRITE_LOW_PRIORITY :
  146.     lock_type)))
  147.     DBUG_RETURN(-1);
  148.   table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  149.   thd->proc_info="init";
  150.   if (use_generate_table)
  151.     DBUG_RETURN(generate_table(thd,table_list,table));
  152.   table->map=1;
  153.   if (setup_conds(thd,table_list,&conds))
  154.     DBUG_RETURN(-1);
  155.   table->used_keys=table->quick_keys=0; // Can't use 'only index'
  156.   select=make_select(table,0,0,conds,&error);
  157.   if (error)
  158.     DBUG_RETURN(-1);
  159.   if (select && select->check_quick(test(thd->options & SQL_SAFE_UPDATES),
  160.     limit))
  161.   {
  162.     delete select;
  163.     send_ok(&thd->net,0L);
  164.     DBUG_RETURN(0);
  165.   }
  166.   /* If running in safe sql mode, don't allow updates without keys */
  167.   if (!table->quick_keys)
  168.   {
  169.     thd->lex.options|=QUERY_NO_INDEX_USED;
  170.     if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
  171.     {
  172.       delete select;
  173.       send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
  174.       DBUG_RETURN(1);
  175.     }
  176.   }
  177.   (void) table->file->extra(HA_EXTRA_NO_READCHECK);
  178.   if (options & OPTION_QUICK)
  179.     (void) table->file->extra(HA_EXTRA_QUICK);    
  180.   init_read_record(&info,thd,table,select,-1,1);
  181.   ulong deleted=0L;
  182.   thd->proc_info="updating";
  183.   while (!(error=info.read_record(&info)) && !thd->killed)
  184.   {
  185.     if (!(select && select->skipp_record()))
  186.     {
  187.       if (!(error=table->file->delete_row(table->record[0])))
  188.       {
  189. deleted++;
  190. if (!--limit && using_limit)
  191. {
  192.   error= -1;
  193.   break;
  194. }
  195.       }
  196.       else
  197.       {
  198. table->file->print_error(error,MYF(0));
  199. error=0;
  200. break;
  201.       }
  202.     }
  203.   }
  204.   thd->proc_info="end";
  205.   end_read_record(&info);
  206.   (void) table->file->extra(HA_EXTRA_READCHECK);
  207.   if (options & OPTION_QUICK)
  208.     (void) table->file->extra(HA_EXTRA_NORMAL);    
  209.   using_transactions=table->file->has_transactions();
  210.   if (deleted && (error <= 0 || !using_transactions))
  211.   {
  212.     mysql_update_log.write(thd,thd->query, thd->query_length);
  213.     if (mysql_bin_log.is_open())
  214.     {
  215.       Query_log_event qinfo(thd, thd->query, using_transactions);
  216.       if (mysql_bin_log.write(&qinfo) && using_transactions)
  217. error=1;
  218.     }
  219.     if (!using_transactions)
  220.       thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
  221.   }
  222.   if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0))
  223.     error=1;
  224.   if (thd->lock)
  225.   {
  226.     mysql_unlock_tables(thd, thd->lock);
  227.     thd->lock=0;
  228.   }
  229.   delete select;
  230.   if (error >= 0) // Fatal error
  231.     send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0);
  232.   else
  233.   {
  234.     send_ok(&thd->net,deleted);
  235.     DBUG_PRINT("info",("%d records deleted",deleted));
  236.   }
  237.   DBUG_RETURN(0);
  238. }