/*	DISTINCT.C	- 
**
**
** Copyright (c) 1996  Hughes Technologies Pty Ltd
**
** Permission to use, copy, and distribute for non-commercial purposes,
** is hereby granted without fee, providing that the above copyright
** notice appear in all copies and that both the copyright notice and this
** permission notice appear in supporting documentation.
**
** The software may be modified for your own purposes, but modified versions
** may not be distributed.
**
** This software is provided "as is" without any expressed or implied warranty.
**
**
*/


#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#ifdef OS2
#  include <types.h>
#else
#  include <arpa/inet.h>
#  include <unistd.h>
#  include <stdlib.h>
#  include <string.h>
#endif


#ifdef OS2
#  include <common/mman.h>
#else
#  include <sys/mman.h>
#endif

#ifdef HAVE_DIRENT_H
#  ifdef OS2
#    include <common/dirent.h>
#  else
#    include <dirent.h>
#  endif
#endif

#ifdef HAVE_SYS_DIR_H
#  include <sys/dir.h>
#endif

#ifdef WIN32
#  include <winsock.h>
#endif

#include <common/debug.h>
#include <common/site.h>
#include <common/portability.h>

#include "avl_tree.h"


#if defined(OS2) || defined(WIN32)
#  include "msql_yacc.h"
#else
#  include "y.tab.h"
#endif

#define _MSQL_SERVER_SOURCE

#include "msql_priv.h"
#include "msql.h"
#include "errmsg.h"

#define REG             register




extern	char	*packet,
		errMsg[];
extern	int	outSock;


#define AVL_DISTINCT


#ifdef AVL_DISTINCT


int createDistinctTable(entry)
	cache_t	*entry;
{
	avltree *tree;
	avl_nod	*node;
	row_t	row;
	u_int	curRowNum;
	int	flist[MAX_FIELDS];
	

	if(initTable(entry,FULL_REMAP) < 0)
	{
		return(-1);
	}
	if(entry->sblk->numRows == 0)
	{
		return(0);
	}
	if (msqlSetupFields(entry,flist,entry->def) < 0)
	{
		return(-1);
	}

	tree = avlMemCreate(entry->rowLen,AVL_BYTE,AVL_DUP);

	curRowNum = 0;
	while(rowRead(entry,&row,curRowNum) > 0)
	{
		if (!row.header->active)
		{
			curRowNum++;
			continue;
		}

		node = avlLookup(tree,row.data,AVL_EXACT);
		if (node)
		{
			row.header->active = 0;
			/* deleteRow(entry,curRowNum); */
		}
		else
		{
			avlInsert(tree,row.data,0);
		}
		curRowNum++;
	}
	avlClose(tree);
	return(0);
}



#endif


#ifdef OLD_DISTINCT
int createDistinctTable(entry)
	cache_t	*entry;
{

	row_t	row,
		*cur = NULL;
	u_int	rowNum,
		curRowNum;
	int	flist[MAX_FIELDS],
		res;
	

	if(initTable(entry,FULL_REMAP) < 0)
	{
		return(-1);
	}
	if(entry->sblk->numRows == 0)
	{
		return(0);
	}
	if (msqlSetupFields(entry,flist,entry->def) < 0)
	{
		return(-1);
	}

	curRowNum = 0;
	while(rowRead(entry,&row,curRowNum) > 0)
	{
		if (!row.header->active)
		{
			curRowNum++;
			continue;
		}
		cur = dupRow(entry,&row, &(entry->row));
		rowNum = curRowNum;

		while(rowRead(entry,&row,rowNum) > 0)
		{
			if (!row.header->active)
			{
				rowNum++;
				continue;
			}
			if (rowNum == curRowNum)
			{
				rowNum++;
				continue;
			}
			if (*(cur->data) != *(row.data))
			{
				rowNum++;
				continue;
			}

			/* RNS
			 * Originally, bcmp was used on the whole row,
			 * when there were not TEXT fields, but it does
			 * not properly handle NULL values.
			 * So, now, everything is done the long way.
			 * And, I have removed all the haveVarChar stuff.
			 */
			res = checkDupRow(entry,cur->data,row.data);
			if (res == 0)
			{
				deleteRow(entry,rowNum);
			}
			rowNum++;
		}
		curRowNum++;
	}
	return(0);
}


#endif
