/*      sysvar.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.
**
** ID = "$Id:"
**
*/


#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <time.h>

#ifdef HAVE_DIRENT_H
#  include <dirent.h>
#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 <regexp/regexp.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    errMsg[];


static	int	sysSeqInit = 1,
		sysTimeInit = 1,
		sysDateInit = 1;


/* In-lined version of intMatch() */

#define intMatch(v1,v2,op,result)                       \
{                                                       \
        switch(op)                                      \
        {                                               \
                case EQ_OP:                             \
                        result = (v1 == v2);            \
                        break;                          \
                case NE_OP:                             \
                        result = (v1 != v2);            \
                        break;                          \
                case LT_OP:                             \
                        result = (v1 < v2);             \
                        break;                          \
                case LE_OP:                             \
                        result = (v1 <= v2);            \
                        break;                          \
                case GT_OP:                             \
                        result = (v1 > v2);             \
                        break;                          \
                case GE_OP:                             \
                        result = (v1 >= v2);            \
                        break;                          \
        }                                               \
}




void msqlResetSysVars()
{
	sysSeqInit = 1;
	sysDateInit = 1;
	sysTimeInit = 1;
}



void getSysVar(entry,row,curField)
        cache_t *entry;
        row_t   *row;
	field_t	*curField;
{
	static	int	curSequence,
			curDate,
			curTime;
	char	*tmp;

	safeFree(curField->value);
        curField->value = (val_t *)malloc(sizeof(val_t));
	if (strcmp(curField->name, "_timestamp") == 0)
	{
		curField->value->val.intVal = (int) row->header->timestamp;
		curField->value->type = INT_TYPE;
		curField->value->nullVal = 0;
		return;
	}

	if (strcmp(curField->name, "_rowid") == 0)
	{
		curField->value->val.intVal = row->rowID;
		curField->value->type = INT_TYPE;
		curField->value->nullVal = 0;
		return;
	}

	if (strcmp(curField->name, "_seq") == 0)
	{
		if (sysSeqInit == 0)
		{
			curField->value->val.intVal = curSequence;
		}
		else
		{
			curField->value->val.intVal = 
				entry->sblk->sequence.value;
			entry->sblk->sequence.value += 
				entry->sblk->sequence.step;
			sysSeqInit = 0;
			curSequence = curField->value->val.intVal;
		}
		curField->value->type = INT_TYPE;
		curField->value->nullVal = 0;
		return;
	}

	if (strcmp(curField->name, "_sysdate") == 0)
	{
		if (sysDateInit == 0)
		{
			curField->value->val.intVal = curDate;
		}
		else
		{
			tmp = (char *)msqlUnixTimeToDate(time(NULL));
			curField->value->val.intVal = 
				__msqlScanDate(tmp);
			curField->value->type = DATE_TYPE;
			curField->value->nullVal = 0;
			sysDateInit = 0;
			curDate = curField->value->val.intVal;
		}
		return;
	}

	if (strcmp(curField->name, "_systime") == 0)
	{
		if (sysTimeInit == 0)
		{
			curField->value->val.intVal = curTime;
		}
		else
		{
			tmp = (char *)msqlUnixTimeToTime(time(NULL));
			curField->value->val.intVal = 
				__msqlScanTime(tmp);
			curField->value->type = TIME_TYPE;
			curField->value->nullVal = 0;
			sysTimeInit = 0;
			curTime = curField->value->val.intVal;
		}
		return;
	}

	if (strcmp(curField->name, "_user") == 0)
	{
		curField->value->val.charVal = (u_char *)getCurUser();
		curField->value->type = CHAR_TYPE;
		curField->value->nullVal = 0;
		return;
	}
}



field_t *getSysVarDef(curField)
	field_t	*curField;
{

	field_t	*new;

	new = (field_t *)malloc(sizeof(field_t));
	strcpy(new->table, curField->table);
	strcpy(new->name, curField->name);
	new->value = NULL;
	new->sysvar = 1;
	new->entry = NULL;
	new->fieldID = -1;
	new->flags = -1;
	new->null = 0;

	if (strcmp(curField->name, "_timestamp") == 0)
	{
		new->type = INT_TYPE;
		new->length = new->dataLength = sizeof(int);
		return(new);
	}

	if (strcmp(curField->name, "_rowid") == 0)
	{
		new->type = INT_TYPE;
		new->length = new->dataLength = sizeof(int);
		return(new);
	}

	if (strcmp(curField->name, "_seq") == 0)
	{
		new->type = INT_TYPE;
		new->length = new->dataLength = sizeof(int);
		return(new);
	}

	if (strcmp(curField->name, "_sysdate") == 0)
	{
		new->type = DATE_TYPE;
		new->length = new->dataLength = sizeof(int);
		return(new);
	}

	if (strcmp(curField->name, "_systime") == 0)
	{
		new->type = TIME_TYPE;
		new->length = new->dataLength = sizeof(int);
		return(new);
	}

	if (strcmp(curField->name, "_user") == 0)
	{
		new->type = CHAR_TYPE;
		new->length = new->dataLength = 16;
		return(new);
	}
	return(NULL); /* Just for lint */
}


int compareSysVar(entry,row,cond, value)
        cache_t *entry;
        row_t   *row;
	cond_t	*cond;
	val_t	*value;
{
	int	intVal,
		result;

	if (strcmp(cond->name, "_timestamp") == 0)
	{
		intVal = (int)row->header->timestamp;
	}

	if (strcmp(cond->name, "_rowid") == 0)
	{
		intVal = row->rowID;
	}

	switch(cond->type)
	{
		case INT_TYPE:
			intMatch(intVal, value->val.intVal,
				cond->op, result);
			break;
	}
	return(result);
}


int checkSysVar(entry,curField)
	cache_t	*entry;
	field_t	*curField;
{

	if (strcmp(curField->name, "_timestamp") == 0 ||
	    strcmp(curField->name, "_rowid") == 0)
	{
		curField->type = INT_TYPE;
		curField->length = 4;
		curField->flags = 0;
		curField->entry = NULL;
		return(0);
	}
	if(strcmp(curField->name, "_user") == 0)
	{
		curField->type = CHAR_TYPE;
		curField->length = 16;
		curField->flags = 0;
		curField->entry = NULL;
		return(0);
	}
	if(strcmp(curField->name, "_sysdate") == 0)
	{
		curField->type = DATE_TYPE;
		curField->length = 4;
		curField->flags = 0;
		curField->entry = NULL;
		return(0);
	}
	if(strcmp(curField->name, "_systime") == 0)
	{
		curField->type = TIME_TYPE;
		curField->length = 4;
		curField->flags = 0;
		curField->entry = NULL;
		return(0);
	}
	if(strcmp(curField->name, "_seq") == 0)
	{
		if (entry->sblk->sequence.step == 0)
		{
			strcpy(errMsg,"No sequence defined for this table");
			msqlDebug(MOD_ERR,"No sequence defined for this table");
			return(-2);
		}
		curField->type = UINT_TYPE;
		curField->length = 4;
		curField->flags = 0;
		curField->entry = NULL;
		return(0);
	}
	return(-1);
}



int getSysVarType(name)
	char	*name;
{

	if (strcmp(name, "_timestamp") == 0 ||
	    strcmp(name, "_rowid") == 0)
	{
		return(INT_TYPE);
	}
	if(strcmp(name, "_sysdate") == 0)
	{
		return(DATE_TYPE);
	}
	if(strcmp(name, "_systime") == 0)
	{
		return(TIME_TYPE);
	}
	if(strcmp(name, "_user") == 0)
	{
		return(CHAR_TYPE);
	}
	if(strcmp(name, "_seq") == 0)
	{
		return(UINT_TYPE);
	}
	return(-1);
}


int checkSysVarCond(curCond)
	cond_t	*curCond;
{

	if (strcmp(curCond->name, "_timestamp") == 0 )
	{
		curCond->type = INT_TYPE;
		curCond->length = 4;
		return(0);
	}
	if(strcmp(curCond->name, "_rowid") == 0)
	{
		curCond->type = INT_TYPE;
		curCond->length = 4;
		return(0);
	}
	if(strcmp(curCond->name, "_seq") == 0)
	{
		strcpy(errMsg,"Can't use _seq in conditions");
		msqlDebug(MOD_ERR,"Can't use _seq in conditions");
		return(-2);
	}
	if(strcmp(curCond->name, "_user") == 0)
	{
		strcpy(errMsg,"Can't use _user in conditions");
		msqlDebug(MOD_ERR,"Can't use _user in conditions");
		return(-2);
	}
	if(strcmp(curCond->name, "_sysdate") == 0)
	{
		strcpy(errMsg,"Can't use _sysdate in conditions");
		msqlDebug(MOD_ERR,"Can't use _sysdate in conditions");
		return(-2);
	}
	if(strcmp(curCond->name, "_systime") == 0)
	{
		strcpy(errMsg,"Can't use _systime in conditions");
		msqlDebug(MOD_ERR,"Can't use _systime in conditions");
		return(-2);
	}
	return(-1);
}


