Commit dcac1079 authored by Sinisa@sinisa.nasamreza.org's avatar Sinisa@sinisa.nasamreza.org
Browse files

Merge sinisa@work.mysql.com:/home/bk/mysql-4.0

into sinisa.nasamreza.org:/mnt/hdc/Sinisa/mysql-4.0
parents 957e6b39 8968152b
Loading
Loading
Loading
Loading
+0 −372
Original line number Diff line number Diff line
@@ -295,12 +295,10 @@ int mysql_delete(THD *thd,

#define MEM_STRIP_BUF_SIZE sortbuff_size

#ifndef SINISAS_STRIP
int refposcmp2(void* arg, const void *a,const void *b)
{
  return memcmp(a,b,(int) arg);
}
#endif

multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
			   thr_lock_type lock_option_arg,
@@ -310,12 +308,7 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
    do_delete(false)
{
  uint counter=0;
#ifdef SINISAS_STRIP
  tempfiles = (IO_CACHE **) sql_calloc(sizeof(IO_CACHE *)* num_of_tables);
  memory_lane = (byte *)sql_alloc(MAX_REFLENGTH*MEM_STRIP_BUF_SIZE);
#else
  tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
#endif

  (void) dt->table->file->extra(HA_EXTRA_NO_READCHECK);
  /* Don't use key read with MULTI-TABLE-DELETE */
@@ -326,21 +319,10 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
    TABLE *table=dt->table;
    (void) dt->table->file->extra(HA_EXTRA_NO_READCHECK);
    (void) dt->table->file->extra(HA_EXTRA_NO_KEYREAD);
#ifdef SINISAS_STRIP
    tempfiles[counter]=(IO_CACHE *) sql_alloc(sizeof(IO_CACHE));
    if (open_cached_file(tempfiles[counter], mysql_tmpdir,TEMP_PREFIX,
			 DISK_BUFFER_SIZE, MYF(MY_WME)))
    {
      my_error(ER_CANT_OPEN_FILE,MYF(0),(tempfiles[counter])->file_name,errno);
      thd->fatal_error=1;
      return;
    }
#else
    tempfiles[counter] = new Unique (refposcmp2,
				     (void *) table->file->ref_length,
				     table->file->ref_length,
				     MEM_STRIP_BUF_SIZE);
#endif
  }
}

@@ -403,13 +385,7 @@ multi_delete::~multi_delete()
  for (uint counter = 0; counter < num_of_tables-1; counter++)
  {
    if (tempfiles[counter])
    {
#ifdef SINISAS_STRIP
      end_io_cache(tempfiles[counter]);
#else
      delete tempfiles[counter];
#endif
    }
  }
}

@@ -443,11 +419,7 @@ bool multi_delete::send_data(List<Item> &values)
    }
    else
    {
#ifdef SINISAS_STRIP
      error=my_b_write(tempfiles[secure_counter],table->file->ref,rl);
#else
      error=tempfiles[secure_counter]->unique_add(table->file->ref);
#endif
      if (error)
      {
	error=-1;
@@ -459,330 +431,6 @@ bool multi_delete::send_data(List<Item> &values)
}


#ifdef SINISAS_STRIP
static inline int COMP (byte *ml,uint len,unsigned int left, unsigned int right)
{
  return memcmp(ml + left*len,ml + right*len,len);
}

#define EX(ML,LEN,LLLEFT,RRRIGHT) \
ptr1 = ML + LLLEFT*LEN;\
ptr2 = ML + RRRIGHT*LEN;\
memcpy(tmp,ptr1,LEN);\
memcpy(ptr1,ptr2,LEN);\
memcpy(ptr2,tmp,LEN);\



static void  qsort_mem_pieces(byte *ml, uint length,  unsigned short pivotP, unsigned int nElem) 
{
  unsigned int     leftP, rightP, pivotEnd, pivotTemp, leftTemp;
  unsigned  int  lNum; byte tmp [MAX_REFLENGTH], *ptr1, *ptr2;
  int       retval;
tailRecursion:
  if (nElem <= 1) return;
  if (nElem == 2) 
  {
    if (COMP(ml,length,pivotP, rightP = pivotP + 1) > 0)
    {
      EX(ml,length,pivotP, rightP);
    }
    return;
  }

  rightP = (nElem - 1) + pivotP;
  leftP  = (nElem >> 1) + pivotP;

/*  sort the pivot, left, and right elements for "median of 3" */

  if (COMP (ml,length,leftP, rightP) > 0)
  {	
    EX (ml,length,leftP, rightP);
  }
  if (COMP (ml,length,leftP, pivotP) > 0)
  {
    EX (ml,length,leftP, pivotP);
  }
  else if (COMP (ml,length, pivotP, rightP) > 0)
  {
    EX (ml,length,pivotP, rightP);
  }
	
  if (nElem == 3) {
    EX (ml,length,pivotP, leftP);
    return;
  }

/*  now for the classic Hoare algorithm */
  
  leftP = pivotEnd = pivotP + 1;

  do {
    while ((retval = COMP (ml,length, leftP, pivotP)) <= 0) 
    {
      if (retval == 0) {
	EX(ml,length,leftP, pivotEnd);
	pivotEnd++;
      }
      if (leftP < rightP)
	leftP++;
      else
	goto qBreak;
    }
    while (leftP < rightP) {
      if ((retval = COMP(ml,length,pivotP, rightP)) < 0)
	rightP--;
      else 
      {
	EX (ml,length,leftP, rightP);
	if (retval != 0) {
	  leftP++;
	  rightP--;
	}
	break;
      }
    }
  }   while (leftP < rightP);

qBreak:

  if (COMP(ml,length,leftP, pivotP) <= 0)
    leftP++;

  leftTemp = leftP - 1;    pivotTemp = pivotP;

  while ((pivotTemp < pivotEnd) && (leftTemp >= pivotEnd)) 
  {
    EX(ml,length,pivotTemp, leftTemp);
    pivotTemp++;  leftTemp--;
  }

  lNum = leftP - pivotEnd;   nElem = (nElem + pivotP) - leftP;

  /* Sort smaller partition first to reduce stack usage */
  if (nElem < lNum) 
  {
    qsort_mem_pieces(ml,length,leftP, nElem); nElem = lNum;
  }
  else 
  {
    qsort_mem_pieces(ml,length,pivotP, lNum);
    pivotP = leftP;
  }
  goto tailRecursion;
}

static byte * btree_search(byte *lane, byte *key,register int last, uint length)
{
  register int first = 0;
  if (last == first)
  {
    if (!memcmp(lane,key,length)) return lane;
    return (byte *)0;
  }
Recursion_is_too_slow:
  if (last - first < 3)
  {
    if (!memcmp(lane + first*length,key,length)) return lane + first * length;
    if (last == first + 1) return (byte *)0;
    if (!memcmp(lane +  last*length,key,length)) return lane + last * length;
    return (byte *)0;
  }
  else 
  {
    int half = first + (last - first)/2;
    int result = memcmp(lane + half*length,key,length);
    if (!result) return lane + half*length;
    if (result < 0)
    {
      first = half + 1; goto Recursion_is_too_slow;
    }
    else
    {	
      last = half + 1; goto Recursion_is_too_slow;
    }
  }
}

struct written_block {
  byte first[MAX_REFLENGTH], last[MAX_REFLENGTH];
  my_off_t offset;
  uint how_many;
};

static IO_CACHE *strip_duplicates_from_temp (byte *memory_lane, IO_CACHE *ptr, uint ref_length,  int *written)
{
  byte *mem_ptr; my_off_t off = 0;
  int read_error, write_error, how_many_to_read, total_to_read = *written, pieces_in_memory = 0, mem_count,written_rows;
  int offset = written_rows=*written=0;
  int  mem_pool_size = MEM_STRIP_BUF_SIZE * MAX_REFLENGTH / ref_length;
  byte dup_record[MAX_REFLENGTH]; memset(dup_record,'\xFF',MAX_REFLENGTH);
  if (reinit_io_cache(ptr,READ_CACHE,0L,0,0))
    return ptr;
  IO_CACHE *tempptr =  (IO_CACHE *) my_malloc(sizeof(IO_CACHE), MYF(MY_FAE | MY_ZEROFILL));
  if (open_cached_file(tempptr, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
  {
    my_free((gptr) tempptr, MYF (0));
    return ptr;
  }
  DYNAMIC_ARRAY written_blocks;
  VOID(init_dynamic_array(&written_blocks,sizeof(struct written_block),20,50));
  for (;pieces_in_memory < total_to_read;)
  {
    how_many_to_read = total_to_read - pieces_in_memory;  read_error=write_error=0;
    if (how_many_to_read > mem_pool_size) 
      how_many_to_read = mem_pool_size;
    if (my_b_read(ptr, memory_lane, (uint) how_many_to_read * ref_length))
    {
      read_error = 1;
      break;
    }
    pieces_in_memory += how_many_to_read;
    qsort_mem_pieces(memory_lane,0, how_many_to_read, ref_length);
    byte *checking = dup_record,  *cursor=NULL, *mem_end = memory_lane + how_many_to_read * ref_length;
    int opt_unique_pieces, unique_pieces_in_memory=0; write_error=0;
    for (mem_ptr=memory_lane; mem_ptr < mem_end ; mem_ptr += ref_length)
    {
      if (memcmp(mem_ptr,checking, ref_length))
      {
	if (cursor)
	{
	  memmove(cursor,mem_ptr,mem_end - mem_ptr);
	  mem_end -= mem_ptr - cursor;
	  mem_ptr = cursor; cursor = NULL;
	}
	unique_pieces_in_memory++;
	checking = mem_ptr;
      }
      else if (!cursor) cursor = mem_ptr;
    }
    opt_unique_pieces=unique_pieces_in_memory;
    if (written_rows) 
    {
      if (reinit_io_cache(tempptr,READ_CACHE,0L,0,0))  {write_error = -1; break;}
      for (uint i=0 ; i < written_blocks.elements ; i++)
      {
	struct written_block *wbp=dynamic_element(&written_blocks,i,struct written_block*);
	if ((memcmp(memory_lane,wbp->last,ref_length) == 1) || (memcmp(memory_lane + (unique_pieces_in_memory - 1) * ref_length, wbp->first, ref_length) == -1))
	  continue;
	else
	{
	  if (wbp->how_many < 3)
	  {
	    if ((mem_ptr=btree_search(memory_lane,wbp->first,unique_pieces_in_memory-1, ref_length)))
	    {
	      if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
	      memcpy(mem_ptr,dup_record,ref_length);
	    }
	    if (wbp->how_many == 2 && (mem_ptr=btree_search(memory_lane,wbp->last,unique_pieces_in_memory-1, ref_length)))
	    {
	      if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
	      memcpy(mem_ptr,dup_record,ref_length);
	    }
	  }
	  else
	  {
	    byte block[MAX_REFLENGTH * MEM_STRIP_BUF_SIZE]; // 16 K maximum and only temporary !!
	    if (my_b_read(tempptr, block, (uint) wbp->how_many * ref_length))
	    {
	      read_error = 1; goto skip_writting;
	    }
	    if (unique_pieces_in_memory < 3)
	    {
	      if ((mem_ptr=btree_search(block,memory_lane,wbp->how_many - 1, ref_length)))
	      {
		if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
		memcpy(memory_lane,dup_record,ref_length);
	      }
	      if (unique_pieces_in_memory == 2 && (mem_ptr=btree_search(block,memory_lane + ref_length,wbp->how_many - 1, ref_length)))
	      {
		if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
		memcpy(mem_ptr,dup_record,ref_length);
	      }
	    }
	    else
	    {
	      byte *cursor; bool do_check_past;
	      if (unique_pieces_in_memory < wbp->how_many)
	      {
		do_check_past = (memcmp(memory_lane + (unique_pieces_in_memory - 1)*ref_length,wbp->last,ref_length) == 1);
		for (cursor=memory_lane; cursor < memory_lane + unique_pieces_in_memory*ref_length; cursor += ref_length)
		{
		  if ((mem_ptr=btree_search(block,cursor,wbp->how_many - 1, ref_length)))
		  {
		    if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
		    memcpy(cursor,dup_record,ref_length);
		  }
		  else if (do_check_past && (memcmp(cursor,wbp->last,ref_length) == 1)) break;
		}
	      }
	      else
	      {
		do_check_past = (memcmp(memory_lane + (unique_pieces_in_memory - 1)*ref_length,wbp->last,ref_length) == -1);
		for (cursor=block; cursor < block + wbp->how_many*ref_length;cursor += ref_length)
		{
		  if ((mem_ptr=btree_search(memory_lane,cursor,unique_pieces_in_memory-1, ref_length)))
		  {
		    if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
		    memcpy(mem_ptr,dup_record,ref_length);
		  }
		  else if (do_check_past && (memcmp(cursor,memory_lane + (unique_pieces_in_memory - 1)*ref_length,ref_length) == 1)) break;
		}
	      }
	    }
	  }
	}
      }
    }
    reinit_io_cache(tempptr, WRITE_CACHE,off,0,0);
    struct written_block wb; wb.offset = off; wb.how_many=opt_unique_pieces; byte *last;
    if (opt_unique_pieces < unique_pieces_in_memory)
    {
      for (mem_count=0, mem_ptr=memory_lane; mem_count<unique_pieces_in_memory;mem_count++, mem_ptr += ref_length)
      {
	if (memcmp(mem_ptr,dup_record,ref_length)) 
	{
	  if (my_b_write(tempptr,mem_ptr,ref_length))
	  {
	    if (write_error == 9 || write_error == -1) write_error = 0;
	    if (write_error) break;
	  }
	  if (!mem_count) memcpy(wb.first,mem_ptr,ref_length);
	  last = mem_ptr;
	  written_rows++;
	}
      }
      memcpy(wb.last,last,ref_length);
    }
    else
    {
      memcpy(wb.first,memory_lane,ref_length); memcpy(wb.last,memory_lane + (unique_pieces_in_memory -1)*ref_length,ref_length);
      if (my_b_write(tempptr, memory_lane,unique_pieces_in_memory * ref_length))
      {
	write_error = 1; break;
      }
      written_rows += unique_pieces_in_memory;
    }
    off = my_b_tell(tempptr);
    VOID(push_dynamic(&written_blocks,(gptr) &wb));
  skip_writting:
    if (write_error || read_error) break;
  }
  delete_dynamic(&written_blocks);
  if (read_error || write_error)
  {
    close_cached_file(tempptr); end_io_cache(tempptr);
    return ptr;
  }
  else
  {
    close_cached_file(ptr); *written=written_rows; end_io_cache(ptr);
    reinit_io_cache(tempptr,READ_CACHE,0L,0,0); 
    return tempptr;
  }
}

#endif /* SINISAS_STRIP */

/* Return true if some table is not transaction safe */

@@ -845,21 +493,11 @@ int multi_delete::do_deletes (bool from_send_error)
  { 
    TABLE *table = table_being_deleted->table;
    int rl = table->file->ref_length;
#ifdef SINISAS_STRIP
    int num_of_positions =  (int)my_b_tell(tempfiles[counter])/rl;
    if (!num_of_positions) continue;
    tempfiles[counter] = strip_duplicates_from_temp(memory_lane, tempfiles[counter],rl,&num_of_positions);
    if (!num_of_positions)
    {
      error=1; break;
    }
#else
    if (tempfiles[counter]->get(table))
    {
      error=1;
      break;
    }
#endif

#if USE_REGENERATE_TABLE
    // nice little optimization ....
@@ -883,14 +521,7 @@ int multi_delete::do_deletes (bool from_send_error)

    READ_RECORD	info;
    error=0;
#ifdef SINISAS_STRIP
    SQL_SELECT	*select= new SQL_SELECT;
    select->head=table;
    select->file=*tempfiles[counter];
    init_read_record(&info,thd,table,select,0,0);
#else
    init_read_record(&info,thd,table,NULL,0,0);
#endif
    bool not_trans_safe = some_table_is_not_transaction_safe(delete_tables);
    while (!(error=info.read_record(&info)) &&
	   (!thd->killed ||  from_send_error || not_trans_safe))
@@ -905,9 +536,6 @@ int multi_delete::do_deletes (bool from_send_error)
	deleted++;
    }
    end_read_record(&info);
#ifdef SINISAS_STRIP
    delete select;
#endif
    if (error == -1)
      error = 0;
  }
+1 −3
Original line number Diff line number Diff line
@@ -1754,10 +1754,8 @@ mysql_execute_command(void)
      break;
    }
    if (!(res=open_and_lock_tables(thd,(TABLE_LIST *)total->first)))
    {
      res=mysql_union(thd,lex, select_lex->select_number+1);
      if (res==-1) res=0;
    }
    close_thread_tables(thd);
    break;
  }
  case SQLCOM_DROP_TABLE:
+66 −29
Original line number Diff line number Diff line
/* Copyright (C) 2000 MySQL 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 */


/* UNION  of select's */

/* UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com> */


#include "mysql_priv.h"


@@ -6,8 +28,8 @@

int mysql_union(THD *thd,LEX *lex,uint no_of_selects) 
{
  SELECT_LEX *sl, *for_order=&lex->select_lex; uint no=0; int res;
  List<Item> fields;     TABLE *table;
  SELECT_LEX *sl, *for_order=&lex->select_lex; uint no=0; int res=0;
  List<Item> fields;     TABLE *table=(TABLE *)NULL; TABLE_LIST *resulting=(TABLE_LIST *)NULL;
  for (;for_order->next;for_order=for_order->next);
  ORDER *some_order = (ORDER *)for_order->order_list.first;
  for (sl=&lex->select_lex;sl;sl=sl->next, no++)
@@ -38,16 +60,19 @@ int mysql_union(THD *thd,LEX *lex,uint no_of_selects)
	  delete result;
	  return res;
	}
	else
	{
	table=result->table;
	List_iterator<Item> it(*(result->fields));
	Item *item;
	while ((item= it++))
	  fields.push_back(item);
	}
	delete result;
	if (reopen_table(table)) return 1;
	if (!reopen_table(table)) return 1;
	if (!(resulting = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
	  return 1;
	resulting->db=tables->db ? tables->db : thd->db;
	resulting->real_name=table->real_name;
	resulting->name=table->table_name;
	resulting->table=table;
      }
      else
	return -1;
@@ -73,29 +98,41 @@ int mysql_union(THD *thd,LEX *lex,uint no_of_selects)
	return -1;
    }
  }
  if (1) // Meaning if not SELECT ... INTO .... which will be done later
  {
    READ_RECORD	info;
    int error=0;
    if (send_fields(thd,fields,1)) return 1;
    SQL_SELECT	*select= new SQL_SELECT;
    select->head=table;
    select->file=*(table->io_cache);
    init_read_record(&info,thd,table,select,1,1);
    while (!(error=info.read_record(&info)) && !thd->killed)
  select_result *result;
  List<Item> item_list;
  List<Item_func_match> ftfunc_list;
  ftfunc_list.empty();
  if (item_list.push_back(new Item_field(NULL,NULL,"*")))
    return -1;
  if (lex->exchange)
  {
      
      if (error)
    if (lex->exchange->dumpfile)
    {
	table->file->print_error(error,MYF(0));
	break;
      if (!(result=new select_dump(lex->exchange)))
	return -1;
    }
    else
    {
      if (!(result=new select_export(lex->exchange)))
	return -1;
    }
    end_read_record(&info);
    delete select;
  }
  else if (!(result=new select_send()))
    return -1;
  else
  {
    res=mysql_select(thd,resulting,item_list,
		     NULL,
		     ftfunc_list,
		     (ORDER*) NULL,
		     (ORDER*) NULL,
		     NULL,
		     (ORDER*) NULL,
		     thd->options,
		     result);
    if (res)
      result->abort();
  }
  return 0;
  delete result;
  return res;
}