home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / sql_delete.cpp < prev    next >
C/C++ Source or Header  |  2000-11-22  |  7KB  |  246 lines

  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.  
  17.  
  18. /* Delete of records */
  19.  
  20. #include "mysql_priv.h"
  21.  
  22. /*
  23.   Optimize delete of all rows by doing a full generate of the table
  24.   This will work even if the .ISM and .ISD tables are destroyed
  25. */
  26.  
  27. int generate_table(THD *thd, TABLE_LIST *table_list,
  28.               TABLE *locked_table)
  29. {
  30.   char path[FN_REFLEN];
  31.   int error;
  32.   TABLE **table_ptr;
  33.   DBUG_ENTER("generate_table");
  34.  
  35.   thd->proc_info="generate_table";
  36.  
  37.   if(global_read_lock)
  38.   {
  39.     if(thd->global_read_lock)
  40.     {
  41.       my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
  42.            table_list->real_name);
  43.       DBUG_RETURN(-1);
  44.     }
  45.     pthread_mutex_lock(&LOCK_open);
  46.     while (global_read_lock && ! thd->killed ||
  47.        thd->version != refresh_version)
  48.     {
  49.       (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
  50.     }
  51.     pthread_mutex_unlock(&LOCK_open);
  52.   }
  53.  
  54.   
  55.     /* If it is a temporary table, close and regenerate it */
  56.   if ((table_ptr=find_temporary_table(thd,table_list->db,
  57.                       table_list->real_name)))
  58.   {
  59.     TABLE *table= *table_ptr;
  60.     HA_CREATE_INFO create_info;
  61.     table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
  62.     bzero((char*) &create_info,sizeof(create_info));
  63.     create_info.auto_increment_value= table->file->auto_increment_value;
  64.     db_type table_type=table->db_type;
  65.  
  66.     strmov(path,table->path);
  67.     *table_ptr= table->next;        // Unlink table from list
  68.     close_temporary(table,0);
  69.     *fn_ext(path)=0;                // Remove the .frm extension
  70.     ha_create_table(path, &create_info,1);
  71.     if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
  72.                          table_list->real_name, 1))))
  73.     {
  74.       (void) rm_temporary_table(table_type, path);
  75.     }
  76.   }
  77.   else
  78.   {
  79.     (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
  80.            table_list->real_name,reg_ext);
  81.     fn_format(path,path,"","",4);
  82.     VOID(pthread_mutex_lock(&LOCK_open));
  83.     if (locked_table)
  84.       mysql_lock_abort(thd,locked_table);     // end threads waiting on lock
  85.     // close all copies in use
  86.     if (remove_table_from_cache(thd,table_list->db,table_list->real_name))
  87.     {
  88.       if (!locked_table)
  89.       {
  90.     VOID(pthread_mutex_unlock(&LOCK_open));
  91.     DBUG_RETURN(1);                // We must get a lock on table
  92.       }
  93.     }
  94.     if (locked_table)
  95.       locked_table->file->extra(HA_EXTRA_FORCE_REOPEN);
  96.     if (thd->locked_tables)
  97.       close_data_tables(thd,table_list->db,table_list->real_name);
  98.     else
  99.       close_thread_tables(thd,1);
  100.     HA_CREATE_INFO create_info;
  101.     bzero((char*) &create_info,sizeof(create_info));
  102.     *fn_ext(path)=0;                // Remove the .frm extension
  103.     error= ha_create_table(path,&create_info,1) ? -1 : 0;
  104.     if (thd->locked_tables && reopen_tables(thd,1,0))
  105.       error= -1;
  106.     VOID(pthread_mutex_unlock(&LOCK_open));
  107.   }
  108.   if (!error)
  109.   {
  110.     send_ok(&thd->net);        // This should return record count
  111.     mysql_update_log.write(thd,thd->query,thd->query_length);
  112.     if (mysql_bin_log.is_open())
  113.     {
  114.       Query_log_event qinfo(thd, thd->query);
  115.       mysql_bin_log.write(&qinfo);
  116.     }
  117.   }
  118.   DBUG_RETURN(error ? -1 : 0);
  119. }
  120.  
  121.  
  122. int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
  123.          thr_lock_type lock_type, ulong options)
  124. {
  125.   int        error;
  126.   TABLE        *table;
  127.   SQL_SELECT    *select;
  128.   READ_RECORD    info;
  129.   bool         using_limit=limit != HA_POS_ERROR;
  130.   bool            use_generate_table;
  131.   DBUG_ENTER("mysql_delete");
  132.  
  133.   if (!table_list->db)
  134.     table_list->db=thd->db;
  135.   if ((thd->options & OPTION_SAFE_UPDATES) && !conds)
  136.   {
  137.     send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
  138.     DBUG_RETURN(1);
  139.   }
  140.  
  141.   use_generate_table= (!using_limit && !conds &&
  142.                !(specialflag &
  143.              (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
  144.                (thd->options & OPTION_AUTO_COMMIT) &&
  145.                        !(thd->options & OPTION_BEGIN));
  146.   if (use_generate_table && ! thd->open_tables)
  147.   {
  148.     error=generate_table(thd,table_list,(TABLE*) 0);
  149.     if (error <= 0)
  150.       DBUG_RETURN(error);            // Error or ok
  151.   }
  152.   if (!(table = open_ltable(thd,table_list,
  153.                 limit != HA_POS_ERROR ? TL_WRITE_LOW_PRIORITY :
  154.                 lock_type)))
  155.     DBUG_RETURN(-1);
  156.   thd->proc_info="init";
  157.   if (use_generate_table)
  158.     DBUG_RETURN(generate_table(thd,table_list,table));
  159.   table->map=1;
  160.   if (setup_conds(thd,table_list,&conds))
  161.     DBUG_RETURN(-1);
  162.  
  163.   table->used_keys=table->quick_keys=0;        // Can't use 'only index'
  164.   select=make_select(table,0,0,conds,&error);
  165.   if (error)
  166.     DBUG_RETURN(-1);
  167.   if (select && select->check_quick(test(thd->options & SQL_SAFE_UPDATES),
  168.                     limit))
  169.   {
  170.     delete select;
  171.     send_ok(&thd->net,0L);
  172.     DBUG_RETURN(0);
  173.   }
  174.  
  175.   /* If running in safe sql mode, don't allow updates without keys */
  176.   if (!table->quick_keys)
  177.   {
  178.     thd->lex.options|=OPTION_NO_INDEX_USED;
  179.     if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
  180.     {
  181.       delete select;
  182.       send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
  183.       DBUG_RETURN(1);
  184.     }
  185.   }
  186.   (void) table->file->extra(HA_EXTRA_NO_READCHECK);
  187.   if (options & OPTION_QUICK)
  188.     (void) table->file->extra(HA_EXTRA_QUICK);    
  189.   init_read_record(&info,thd,table,select,1,1);
  190.   ulong deleted=0L;
  191.   thd->proc_info="updating";
  192.   while (!(error=info.read_record(&info)) && !thd->killed)
  193.   {
  194.     if (!(select && select->skipp_record()))
  195.     {
  196.       if (!(error=table->file->delete_row(table->record[0])))
  197.       {
  198.     deleted++;
  199.     if (!--limit && using_limit)
  200.     {
  201.       error= -1;
  202.       break;
  203.     }
  204.       }
  205.       else
  206.       {
  207.     table->file->print_error(error,MYF(0));
  208.     error=0;
  209.     break;
  210.       }
  211.     }
  212.   }
  213.   thd->proc_info="end";
  214.   end_read_record(&info);
  215.   (void) table->file->extra(HA_EXTRA_READCHECK);
  216.   if (options & OPTION_QUICK)
  217.     (void) table->file->extra(HA_EXTRA_NORMAL);    
  218.   if (deleted)
  219.   {
  220.     mysql_update_log.write(thd,thd->query, thd->query_length);
  221.     if (mysql_bin_log.is_open())
  222.     {
  223.       Query_log_event qinfo(thd, thd->query);
  224.       mysql_bin_log.write(&qinfo);
  225.     }
  226.   }
  227.   if (ha_autocommit_or_rollback(thd,error >= 0))
  228.     error=1;
  229.   if (thd->lock)
  230.   {
  231.     mysql_unlock_tables(thd, thd->lock);
  232.     thd->lock=0;
  233.   }
  234.   delete select;
  235.   if (error >= 0)                // Fatal error
  236.     send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0);
  237.   else
  238.   {
  239.     send_ok(&thd->net,deleted);
  240.     DBUG_PRINT("info",("%d records deleted",deleted));
  241.   }
  242.   DBUG_RETURN(0);
  243. }
  244.  
  245.  
  246.