Commit 02f00743 authored by monty@donna.mysql.fi's avatar monty@donna.mysql.fi
Browse files

Added Unique class to be used for duplicate removal in multi-table delete.

parent 8685094e
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -19,9 +19,6 @@
  get_ptr_compare(len) returns a pointer to a optimal byte-compare function
  for a array of stringpointer where all strings have size len.
  The bytes are compare as unsigned chars.
  Because the size is saved in a static variable.
  When using threads the program must have called my_init and the thread
  my_init_thread()
  */

#include "mysys_priv.h"
+1 −1
Original line number Diff line number Diff line
@@ -205,7 +205,7 @@ make_tempname (filename)
      strcpy (tmpname, filename);
      strcat (tmpname, "/");
      strcat (tmpname, template);
      mktemp (tmpname);
      mkstemp (tmpname);
      *slash = c;
    }
  else
+2 −2
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
			sql_select.h structs.h table.h sql_udf.h hash_filo.h\
			lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.h \
                        log_event.h mini_client.h sql_repl.h slave.h \
			stacktrace.h
			stacktrace.h sql_sort.h
mysqld_SOURCES =	sql_lex.cc sql_handler.cc \
			item.cc item_sum.cc item_buff.cc item_func.cc \
			item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -67,7 +67,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
			mysqld.cc password.c hash_filo.cc hostname.cc \
			convert.cc sql_parse.cc sql_yacc.yy \
			sql_base.cc table.cc sql_select.cc sql_insert.cc \
			sql_update.cc sql_delete.cc \
			sql_update.cc sql_delete.cc uniques.cc \
			procedure.cc item_uniq.cc sql_test.cc \
			log.cc log_event.cc init.cc derror.cc sql_acl.cc \
			unireg.cc \
+53 −56
Original line number Diff line number Diff line
@@ -22,13 +22,11 @@
#include <stddef.h>			/* for macro offsetof */
#endif
#include <m_ctype.h>
#include "sql_sort.h"

#ifndef THREAD
#define SKIPP_DBUG_IN_FILESORT
#endif
	/* static variabels */

#define MERGEBUFF  7
#define MERGEBUFF2 15

	/* How to write record_ref. */

@@ -36,28 +34,6 @@
if (my_b_write((file),(byte*) (from),param->ref_length)) \
  DBUG_RETURN(1);

typedef struct st_buffpek {		/* Struktur om sorteringsbuffrarna */
  my_off_t file_pos;			/* Where we are in the sort file */
  uchar *base,*key;			/* key pointers */
  ha_rows count;			/* Number of rows in table */
  ulong mem_count;			/* numbers of keys in memory */
  ulong max_keys;			/* Max keys in buffert */
} BUFFPEK;


typedef struct st_sort_param {
  uint sort_length;			/* Length of sortarg */
  uint keys;				/* Max antal nycklar / buffert */
  uint ref_length;			/* Length of record ref. */
  ha_rows max_rows,examined_rows;
  TABLE *sort_form;			/* For quicker make_sortkey */
  SORT_FIELD *local_sortorder;
  SORT_FIELD *end;
#ifdef USE_STRCOLL
  char* tmp_buffer;
#endif
} SORTPARAM;

	/* functions defined in this file */

static char **make_char_array(register uint fields, uint length, myf my_flag);
@@ -70,20 +46,11 @@ static int write_keys(SORTPARAM *param,uchar * *sort_keys,
		      IO_CACHE *tempfile);
static void make_sortkey(SORTPARAM *param,uchar *to,
			 byte *ref_pos);
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
static int merge_many_buff(SORTPARAM *param,uchar * *sort_keys,
			   BUFFPEK *buffpek,
			   uint *maxbuffer, IO_CACHE *t_file);
static uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
			   uint sort_length);
static int merge_buffers(SORTPARAM *param,IO_CACHE *from_file,
			 IO_CACHE *to_file,uchar * *sort_keys,
			 BUFFPEK *lastbuff,BUFFPEK *Fb,
			 BUFFPEK *Tb,int flag);
static int merge_index(SORTPARAM *param,uchar * *sort_keys,
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
		       BUFFPEK *buffpek,
		       uint maxbuffer,IO_CACHE *tempfile,
		       IO_CACHE *outfile);
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
static uint sortlength(SORT_FIELD *sortorder,uint length);

	/* Makes a indexfil of recordnumbers of a sorted database */
@@ -225,12 +192,14 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,

    param.keys=((param.keys*(param.sort_length+sizeof(char*))) /
		param.sort_length-1);
    if (merge_many_buff(&param,sort_keys,buffpek,&maxbuffer,&tempfile))
    if (merge_many_buff(&param,(uchar*) sort_keys,buffpek,&maxbuffer,
			&tempfile))
      goto err;
    if (flush_io_cache(&tempfile) ||
	reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
      goto err;
    if (merge_index(&param,sort_keys,buffpek,maxbuffer,&tempfile,outfile))
    if (merge_index(&param,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
		    outfile))
      goto err;
  }
  if (records > param.max_rows)
@@ -629,7 +598,7 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)

	/* Merge buffers to make < MERGEBUFF2 buffers */

static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
		    BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
{
  register int i;
@@ -652,11 +621,11 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
    lastbuff=buffpek;
    for (i=0 ; i <= (int) *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
    {
      if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++,
      if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
			buffpek+i,buffpek+i+MERGEBUFF-1,0))
	break;					/* purecov: inspected */
    }
    if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++,
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
		      buffpek+i,buffpek+ *maxbuffer,0))
      break;					/* purecov: inspected */
    if (flush_io_cache(to_file))
@@ -675,7 +644,7 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
	/* Read data to buffer */
	/* This returns (uint) -1 if something goes wrong */

static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
		    uint sort_length)
{
  register uint count;
@@ -697,8 +666,8 @@ static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,

	/* Merge buffers to one buffer */

static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
			 IO_CACHE *to_file, uchar **sort_keys,
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
		  IO_CACHE *to_file, uchar *sort_buffer,
		  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
		  int flag)
{
@@ -711,21 +680,21 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
  BUFFPEK *buffpek,**refpek;
  QUEUE queue;
  volatile bool *killed= &current_thd->killed;
  qsort2_cmp    cmp;
  DBUG_ENTER("merge_buffers");

  statistic_increment(filesort_merge_passes, &LOCK_status);

  count=error=0;
  offset=param->sort_length-param->ref_length;
  offset=(sort_length=param->sort_length)-param->ref_length;
  maxcount=(ulong) (param->keys/((uint) (Tb-Fb) +1));
  to_start_filepos=my_b_tell(to_file);
  strpos=(uchar*) sort_keys;
  sort_length=param->sort_length;
  strpos=(uchar*) sort_buffer;
  max_rows=param->max_rows;

  if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
		 (int (*) (void *, byte *,byte*))
		 get_ptr_compare(sort_length),(void*) &sort_length))
		 (cmp=get_ptr_compare(sort_length)),(void*) &sort_length))
    DBUG_RETURN(1);				/* purecov: inspected */
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
  {
@@ -739,6 +708,26 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
    queue_insert(&queue,(byte*) buffpek);
  }

  if (param->unique_buff)
  {
    /* 
       Called by Unique::get()
       Copy the first argument to param->unique_buff for unique removal.
       Store it also in 'to_file'.

       This is safe as we know that there is always more than one element
       in each block to merge (This is guaranteed by the Unique:: algorithm
    */
    buffpek=(BUFFPEK*) queue_top(&queue);
    memcpy(param->unique_buff, buffpek->key, sort_length);
    if (my_b_write(to_file,(byte*) buffpek->key, sort_length))
    {
      error=1; goto err;			/* purecov: inspected */
    }
  }
  else
    cmp=0;					// Not unique

  while (queue.elements > 1)
  {
    if (*killed)
@@ -748,6 +737,12 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
    for (;;)
    {
      buffpek=(BUFFPEK*) queue_top(&queue);
      if (cmp)					// Remove duplicates
      {
	if (!cmp(&sort_length, param->unique_buff, (uchar*) buffpek->key))
	  goto skip_duplicate;
	memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length);
      }
      if (flag == 0)
      {
	if (my_b_write(to_file,(byte*) buffpek->key, sort_length))
@@ -764,6 +759,8 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
	error=0;				/* purecov: inspected */
	goto end;				/* purecov: inspected */
      }

    skip_duplicate:
      buffpek->key+=sort_length;
      if (! --buffpek->mem_count)
      {
@@ -802,7 +799,7 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
    }
  }
  buffpek=(BUFFPEK*) queue_top(&queue);
  buffpek->base=(uchar *) sort_keys;
  buffpek->base= sort_buffer;
  buffpek->max_keys=param->keys;
  do
  {
@@ -845,12 +842,12 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,

	/* Do a merge to output-file (save only positions) */

static int merge_index(SORTPARAM *param, uchar **sort_keys,
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
		       BUFFPEK *buffpek, uint maxbuffer,
		       IO_CACHE *tempfile, IO_CACHE *outfile)
{
  DBUG_ENTER("merge_index");
  if (merge_buffers(param,tempfile,outfile,sort_keys,buffpek,buffpek,
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
		    buffpek+maxbuffer,1))
    DBUG_RETURN(1);				/* purecov: inspected */
  DBUG_RETURN(0);
+29 −0
Original line number Diff line number Diff line
@@ -567,3 +567,32 @@ class user_var_entry
  Item_result type;
};

/* Class for unique (removing of duplicates) */

class Unique :public Sql_alloc
{
  DYNAMIC_ARRAY file_ptrs;
  ulong max_elements, max_in_memory_size;
  IO_CACHE file;
  TREE tree;
  char *record_pointers;
  bool flush();

public:
  ulong elements;
  Unique(qsort_cmp2 comp_func, uint size, ulong max_in_memory_size_arg);
  ~Unique();
  inline bool Unique::unique_add(gptr ptr)
  {
    if (tree.elements_in_tree > max_elements && flush())
      return 1;
    return tree_insert(&tree,ptr,0);
  }

  bool get(TABLE *table);

  friend int unique_write_to_file(gptr key, Unique *unique,
				  element_count count);
  friend int unique_write_to_ptrs(gptr key, Unique *unique,
				  element_count count);
};
Loading