/*	mod_msql.c	- 
**
**
** Copyright (c) 1995-96  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 <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <time.h>
#include "lite.h"
#include "msql/msql.h"


extern  sym_t   *externReturn;



void doMsqlConnect(params)
	plist_t *params;
{
	int	sock;
	char	*host = NULL;

	if (params)
	{
		if (params->sym->type != TYPE_CHAR)
		{
			setError("Invalid parameter");
			externReturn = createIntSymbol(-1);
			return;
		}
		host = params->sym->val;
		if (params->next)
		{
			setError("$errmsg", "Invalid parameter count");
			externReturn = createIntSymbol(-1);
			return;
		}
	}
	if ((sock = msqlConnect(host)) < 0)
	{
		setError(msqlErrMsg);
		externReturn = createIntSymbol(-1);
	}
	else
		externReturn = createIntSymbol(sock);
}

void doMsqlClose(params)
	plist_t *params;
{
	int	sock;

	sock = (int) * (int *)params->sym->val;
	msqlClose(sock);
	externReturn = createIntSymbol(0);
}


void doMsqlSelectDB(params)
	plist_t	*params;
{
	char	*dbName;
	int	sock;


	sock = (int) * (int *)params->sym->val;
	dbName = params->next->sym->val;
	if (msqlSelectDB(sock,dbName) < 0)
	{
		setError(msqlErrMsg);
		externReturn = createIntSymbol(-1);
	}
	else
	{
		externReturn = createIntSymbol(0);
	}
}




void doMsqlQuery(params)
	plist_t	*params;
{
	char	*query;
	int	res,
		sock;


	sock = (int) * (int *)params->sym->val;
	query = params->next->sym->val;
	res = msqlQuery(sock,query);
	if (res < 0)
	{
		setError(msqlErrMsg);
	}
	externReturn = createIntSymbol(res);
}


void doMsqlStoreResult(params)
	plist_t	*params;
{
	m_result	*res;
	u_int		id;

	res = msqlStoreResult();
	id = storeObject((char *)res);
	externReturn = createIntSymbol(id);
}


void doMsqlFreeResult(params)
	plist_t	*params;
{
	int	id;
	m_result	*res;

	id = (int) * (int*) params->sym->val;
	res = (m_result *)deleteObject(id);
	if (res)
	{
		msqlFreeResult(res);
	}
}



void doMsqlFetchRow(params)
	plist_t	*params;
{
	u_int	id;
	int	numFields,
		index;
	sym_t	*array,
		*sym;
	m_row	row;
	m_result *res;

	id = (u_int) * (u_int*)params->sym->val;
	res = (m_result *)fetchObject(id);
	if (!res)
	{
		runError("Bad Result Handle");
		exit(1);
	}

	numFields = msqlNumFields(res);
	row = msqlFetchRow(res);
	if (!row)
	{
		return;
	}
	array = createArray();	
	index = 0;
	while (index < numFields)
	{
		if (row[index])
		{
			sym = createCharSymbol(row[index]);
			symSetArrayElement(array,index, sym);
		}
		index++;
	}
	externReturn = array;
}


void doMsqlDataSeek(params)
	plist_t	*params;
{
	int	pos;
	u_int	id;
	m_result *res;

	id = (u_int) * (u_int *)params->sym->val;
	pos = (int) * (int *)params->next->sym->val;

	res = (m_result *)fetchObject(id);
	if (!res)
	{
		return;
	}
	msqlDataSeek(res,pos);
}


void doMsqlNumRows(params)
	plist_t	*params;
{
	int	numRows;
	u_int	id;
	m_result *res;

	id = (u_int) * (u_int *)params->sym->val;
	res = (m_result *)fetchObject(id);
	if (!res)
	{
                return;
	}
	numRows = msqlNumRows(res);
	externReturn = createIntSymbol(numRows);
}



void doMsqlFetchField(params)
	plist_t	*params;
{
	u_int	id;
	int	index;
	sym_t	*array,
		*sym;
	m_field	*field;
	m_result *res;

	id = (u_int) * (u_int*)params->sym->val;
	res = (m_result *)fetchObject(id);
	if (!res)
	{
		return;
	}

	field = msqlFetchField(res);
	if (!field)
	{
		return;
	}
	array = createArray();	
	index = 0;
	sym = createCharSymbol(field->name);
	symSetArrayElement(array,index++,sym);
	sym = createCharSymbol(field->table);
	symSetArrayElement(array,index++,sym);
	sym = createIntSymbol(field->type);
	symSetArrayElement(array,index++,sym);
	sym = createIntSymbol(field->length);
	symSetArrayElement(array,index++,sym);
	sym = createIntSymbol(field->flags);
	symSetArrayElement(array,index++,sym);
	externReturn = array;
}


void doMsqlFieldSeek(params)
	plist_t	*params;
{
	int	pos;
	u_int	id;
	m_result *res;

	id = (u_int) * (u_int *)params->sym->val;
	pos = (int) * (int *)params->next->sym->val;

	res = (m_result *)fetchObject(id);
	if (!res)
	{
		return;
	}
	msqlFieldSeek(res,pos);
}


void doMsqlNumFields(params)
	plist_t	*params;
{
	int	numFields;
	u_int	id;
	m_result *res;

	id = (u_int) * (u_int *)params->sym->val;
	res = (m_result *)fetchObject(id);
	if (!res)
	{
                return;
	}
	numFields = msqlNumFields(res);
	externReturn = createIntSymbol(numFields);
}



void doMsqlListDBs(params)
	plist_t	*params;
{
	m_result *res;
	m_row	cur;
	sym_t	*array,
		*sym;
	int	index,
		sock;

	sock = (int) * (int *)params->sym->val;
	res = msqlListDBs(sock);
	if (!res)
	{
		return;
	}

	index = 0;
	array = createArray();	
	cur = msqlFetchRow(res);
	while(cur)
	{
		sym = createCharSymbol(cur[0]);
		symSetArrayElement(array,index++,sym);
		cur = msqlFetchRow(res);
	}
	msqlFreeResult(res);
	externReturn = array;
}


void doMsqlListTables(params)
	plist_t	*params;
{
	m_result *res;
	m_row	cur;
	sym_t	*array,
		*sym;
	int	index,
		sock;

	sock = (int) * (int *)params->sym->val;
	res = msqlListTables(sock);
	if (!res)
	{
		return;
	}

	index = 0;
	array = createArray();	
	cur = msqlFetchRow(res);
	while(cur)
	{
		sym = createCharSymbol(cur[0]);
		symSetArrayElement(array,index++,sym);
		cur = msqlFetchRow(res);
	}
	msqlFreeResult(res);
	externReturn = array;
}


static 	m_result *fields = NULL;

void doMsqlInitFieldList(params)
	plist_t	*params;
{
	char	*table;
	int	sock;

	sock = (int) * (int *)params->sym->val;
	table = params->next->sym->val;
	if (fields)
		msqlFreeResult(fields);
	fields = msqlListFields(sock,table);
	if (!fields)
	{
		externReturn = createIntSymbol(-1);
	}
	else
	{
		externReturn = createIntSymbol(0);
	}
}


void doMsqlListField(params)
	plist_t	*params;
{
	sym_t	*array,
		*sym;
	m_field	*field;
	int	index;

	if (!fields)
	{
		return;
	}

	field = msqlFetchField(fields);
	if (!field)
	{
		return;
	}

	array = createArray();	
	index = 0;
	sym = createCharSymbol(field->name);
	symSetArrayElement(array,index++, sym);
	sym = createCharSymbol(field->table);
	symSetArrayElement(array,index++, sym);
	sym = createIntSymbol(field->type);
	symSetArrayElement(array,index++, sym);
	sym = createIntSymbol(field->length);
	symSetArrayElement(array,index++, sym);
	sym = createIntSymbol(field->flags);
	symSetArrayElement(array,index++, sym);
	externReturn = array;
}



void doMsqlEncode(params)
	plist_t	*params;
{
	char	*str,
		*new,
		*cp1,
		*cp2;

	str = params->sym->val;
	new = (char *)malloc(2 * strlen(str));
	cp1 = str;
	cp2 = new;
	while(*cp1)
	{
		if (*cp1 == '\\')
		{
			*cp2++ = *cp1++;
		}
		else
		if (*cp1=='\'' || *cp1=='[' || *cp1==']' || *cp1=='^' ||
		*cp1=='$' )
		{
			*cp2++ = '\\';
		}
		*cp2++ = *cp1++;
	}
	*cp2 = 0;
	externReturn = createCharSymbol(new);
	free(new);
}



void doMsqlDateToUnixTime(params)
	plist_t	*params;
{
	char	*date;
	time_t	res;

	date = params->sym->val;
	res = msqlDateToUnixTime(date);
	externReturn = createUintSymbol(res);
}


void doMsqlUnixTimeToDate(params)
	plist_t	*params;
{
	char	*date;
	time_t	time;

	time = (int) * (int *)params->sym->val;
	date = msqlUnixTimeToDate(time);
	externReturn = createCharSymbol(date);
}



void doMsqlTimeToUnixTime(params)
	plist_t	*params;
{
	char	*time;
	time_t	res;

	time = params->sym->val;
	res = msqlTimeToUnixTime(time);
	externReturn = createUintSymbol(res);
}


void doMsqlUnixTimeToTime(params)
	plist_t	*params;
{
	char	*time;
	time_t	utime;

	utime = (time_t) * (int *)params->sym->val;
	time = msqlUnixTimeToTime(utime);
	externReturn = createCharSymbol(time);
}


void doMsqlSumTimes(params)
	plist_t	*params;
{
	char	*time1,
		*time2,
		*result;

	time1 = params->sym->val;
	time2 = params->next->sym->val;
	result = (char *)msqlSumTimes(time1,time2);
	externReturn = createCharSymbol(result);
}


void doMsqlDateOffset(params)
	plist_t	*params;
{
	char	*date,
		*result;
	int	dOff,
		mOff,
		yOff;

	date = params->sym->val;
	dOff = (int) * (int*)params->next->sym->val;
	mOff = (int) * (int*)params->next->next->sym->val;
	yOff = (int) * (int*)params->next->next->next->sym->val;
	result = (char *)msqlDateOffset(date,dOff, mOff, yOff);
	externReturn = createCharSymbol(result);
}


void doMsqlDiffTimes(params)
	plist_t	*params;
{
	char	*time1,
		*time2,
		*result;

	time1 = params->sym->val;
	time2 = params->next->sym->val;
	result = (char *)msqlDiffTimes(time1,time2);
	externReturn = createCharSymbol(result);
}


void doMsqlDiffDates(params)
	plist_t	*params;
{
	char	*date1,
		*date2;
	int	result;

	date1 = params->sym->val;
	date2 = params->next->sym->val;
	result = msqlDiffDates(date1,date2);
	externReturn = createIntSymbol(result);
}



void initMsqlModule()
{
}
