#include "zmsql.h"
#include <string.h>


ZmSQL::ZmSQL(ZmSQLConnection* p):ZSQL(p)
{
Initialize();
Connection=p;
}

void ZmSQL::Initialize()
{
ZSQL::Initialize();
Result=NULL;
CurrRecord=0;
}


int ZmSQL::Open(char* sql,...)
{
char temp[100];
m_field* fld;
int i=0;
va_list argptr;

va_start(argptr,sql);
vsprintf(SQLString,sql,argptr);
va_end(argptr);

if(Result&&Connection)	{
	Close();
	}
ZSQL::Open(SQLString);

if(Connection)
if(msqlQuery(Connection->GetDB(),SQLString)==-1)	{
	PrintError();
	return 0;
	}
#ifndef PLATFORM_MSWINDOWS
if(strncasecmp(SQLString,"select",6))	{
#else
if(strncmpi(SQLString,"select",6))	{
#endif
	return 1;
	}
Result=msqlStoreResult();
if(Result==NULL)	{
	PrintError();
	return 0;
	}
while((fld=msqlFetchField(Result))!=NULL)	
	memcpy(&Field[i++],fld,sizeof(m_field));
return 1;
}

void ZmSQL::Close()
{
if(Result)	{
	msqlFreeResult(Result);
	Result=NULL;
	}
}

int ZmSQL::GetSQLData(int col,char* res,int len)
{

if(col>=GetNumCols()||Row==NULL)
        return 0;
if(Row[col]==NULL)	{
	res[0]=0;
	return 1;
	}
strncpy(res,(char*)Row[col],len-1);
res[len-1]=0;
return 1;
}

int ZmSQL::GetSQLData(int col,int* res)
{
if(col>=GetNumCols()||Row==NULL)
	return 0;
if(Row[col]==NULL)	
	*res=0;
else
	*res=atoi((char*)Row[col]);
return 1;
}
int ZmSQL::GetSQLData(int col,float* res)
{
if(col>=GetNumCols()||Row==NULL)
        return 0;
if(Row[col]==NULL)	
	*res=0.0;
else
	*res=atof((char*)Row[col]);
return 1;
}

int ZmSQL::GetSQLData(int col,double* res)
{
if(col>=GetNumCols()||Row==NULL)
        return 0;
if(Row[col]==NULL)	
	*res=0.0;
else
	*res=strtod((char*)Row[col],(char**)NULL);
return 1;
}

int ZmSQL::GetNextRecord()
{
if(Result==NULL)
	return 0;
Row=msqlFetchRow(Result);
if(Row==NULL)
	return 0;
CurrRecord++;
return 1;
}

int ZmSQL::GetFieldInfo(int pos ,ZField* fld)
{
if(Result==NULL||pos>=GetNumCols())
	return 0;
#ifdef _Windows
wsprintf(fld->Name,"%s",Field[pos].name);
wsprintf(fld->Table,"%s",Field[pos].table);
wsprintf(fld->FQFN,"%s.%s",fld->Table,fld->Name);
#else
sprintf(fld->Name,"%s",Field[pos].name);
sprintf(fld->Table,"%s",Field[pos].table);
sprintf(fld->FQFN,"%s.%s",fld->Table,fld->Name);
#endif
switch(Field[pos].type)	{
	case INT_TYPE:
		fld->Type=INT_FLD;
		break;
	case REAL_TYPE:
		fld->Type=REAL_FLD;
		break;
	case CHAR_TYPE:
		fld->Type=CHAR_FLD;
		break;
	default:
		return 0;
	}
fld->Length=Field[pos].length;
fld->Scale=0;
fld->Precision=0;
if(IS_PRI_KEY(Field[pos].flags))
	fld->Key=1;
else
	fld->Key=0;
if(IS_NOT_NULL(Field[pos].flags))
	fld->Nullable=0;
else
	fld->Nullable=1;
return 1;
}

int ZmSQL::GetNumCols()
{
if(Result==NULL)
	return 0;
return msqlNumFields(Result);
}

int ZmSQL::GetNumRows()
{
if(Result==NULL)
	return 0;
return msqlNumRows(Result);
}

long ZmSQL::Max(char* table,char* fld,char* Where)
{
long maxval=0;
m_result* res;
char SQLString[1000];
m_row Row;

if(Where)
#ifdef _Windows
	wsprintf(SQLString,"select %s from %s where %s",fld,table,Where);
else
	wsprintf(SQLString,"select %s from %s",fld,table);
#else
	sprintf(SQLString,"select %s from %s where %s",fld,table,Where);
else
	sprintf(SQLString,"select %s from %s",fld,table);
#endif
if(msqlQuery(Connection->GetDB(),SQLString)==-1)	{
	PrintError();
	return 0;
	}
res=msqlStoreResult();


while((Row=msqlFetchRow(res))!=NULL)	{
	if(maxval<atoi((char*)Row[0]))
		maxval=atoi((char*)Row[0]);
	}
msqlFreeResult(res);
return maxval;
}

#pragma argsused
long ZmSQL::Min(char* table,char* fld,char* Where)
{
long minval=0;
m_result* res;
char SQLString[1000];
m_row Row;

if(Where)
#ifdef _Windows
	wsprintf(SQLString,"select %s from %s where %s",fld,table,Where);
else
	wsprintf(SQLString,"select %s from %s",fld,table);
#else
	sprintf(SQLString,"select %s from %s where %s",fld,table,Where);
else
	sprintf(SQLString,"select %s from %s",fld,table);
#endif
if(msqlQuery(Connection->GetDB(),SQLString)==-1)	{
	PrintError();
	return 0;
	}
res=msqlStoreResult();
while((Row=msqlFetchRow(res))!=NULL)	{
	if(minval>atoi((char*)Row[0]))
		minval=atoi((char*)Row[0]);
	}
msqlFreeResult(res);
return minval;
}

long ZmSQL::Count(char* table,char* Where)
{
long count=0;
m_result* res;
char sqlstr[1024];

if(Where)
#ifdef _Windows
	wsprintf(sqlstr,"select * from %s where %s",table,Where);
#else
	sprintf(sqlstr,"select * from %s where %s",table,Where);
#endif
else
#ifdef _Windows
	wsprintf(sqlstr,"select * from %s",table);
#else
	sprintf(sqlstr,"select * from %s",table);
#endif
if(msqlQuery(Connection->GetDB(),sqlstr)==-1)	{
	PrintError();
	return 0;
	}
res=msqlStoreResult();
while(msqlFetchRow(res))
	count++;
msqlFreeResult(res);
return count;
}

#pragma argsused
void ZmSQL::PrintError()
{
char temp[1024];
#ifdef _Windows
MessageBox(NULL,msqlErrMsg,"mSQL Error",MB_ICONINFORMATION|MB_OK);
#else
sprintf(temp,"mSQL Error: %s",msqlErrMsg);
printf("%s",temp);
#endif
}

//***********************************************************************
//			ZDBConnection definitions
//***********************************************************************

//For mSQL the connection string comes in as host:db
//You can specify just the db if you want to connect to the internal
//mSQL daemon.
//Currently the username and password are not used.
//In mSQL this would have to be implemented by suid to the username passed to
//this constuctor.

ZmSQLConnection::ZmSQLConnection(char *ConnectInfo,char* User,char* Pass):ZDBConnection(ConnectInfo,User,Pass)
{
char* server;
char* db;

if(ConnectInfo)	{
	db=strstr(ConnectInfo,":");
	if(db)	{
		*db='\0';
		db++;
		server=ConnectInfo;
		SetServer(server);
		}
	else	{
		SetServer(NULL);
		db=ConnectInfo;
		}
	SetDB(db);
	}
else
	SetServer(NULL);
}

ZmSQLConnection::~ZmSQLConnection()
{
ShutDown();
}

BOOL ZmSQLConnection::SetDB(char* db)
{
if(!ConnectedToServer)
	return FALSE;
strcpy(DBName,db);
ConnectedToDB=FALSE;
GetDBInfo(Server,DBName,Field);
ErrCode=msqlSelectDB(hDB,DBName);
if(ErrCode==-1)	{
	return FALSE;
	}
ConnectedToDB=TRUE;
return TRUE;
}

BOOL ZmSQLConnection::SetServer(char* srv)
{
if(ConnectedToServer)
	msqlClose(hDB);
ConnectedToServer=FALSE;
if(srv==NULL)	{
	*Server=0;
#ifdef _Windows
	return FALSE;
#else
	hDB=msqlConnect(Server);
#endif
	}
else	{
	strcpy(Server,srv);
	strcpy(DBName,"");
	hDB=msqlConnect(Server);
	}
if(hDB==-1)
	return FALSE;
ConnectedToServer=TRUE;
return TRUE;
}

char* ZmSQLConnection::GetDBName(int idx)
{
static char DB[256];
m_result* res;
m_row rec;
int i=0;

if(!ConnectedToServer)
	return FALSE;
res=msqlListDBs(hDB);
if(res==NULL)
	return FALSE;
for(i=0;i<=idx;i++)	{
	rec=msqlFetchRow(res);
	if(rec==NULL)	{
		msqlFreeResult(res);
		return NULL;
		}
	}
strcpy(DB,(char*)rec[0]);
msqlFreeResult(res);
return DB;
}
int ZmSQLConnection::GetTableList(char* pServer,char* pDB,ZTableList pList)
{
int sock,i=0;
m_row Row;
m_result* Res;

if((sock=msqlConnect(pServer))==-1)	
	return -1;
if(msqlSelectDB(sock,pDB)==-1)	
	return -1;
if((Res=msqlListTables(sock))==NULL)	
	return -1;
while((Row=msqlFetchRow(Res))!=NULL&&i<MAXNUMTABLES-1)	{
	strncpy(pList[i++],(char*)Row[0],MAXDBNAME-1);
	}
pList[i][0]=0;
msqlFreeResult(Res);
msqlClose(sock);
return i;
}

int ZmSQLConnection::GetDBList(char* pServer,ZDBList pList)
{
int sock,i=0;
m_row Row;
m_result* Res;

if((sock=msqlConnect(pServer))==-1)	
	return -1;
if((Res=msqlListDBs(sock))==NULL)	
	return -1;
while((Row=msqlFetchRow(Res))!=NULL&&i<MAXNUMDBS-1)	{
	strncpy(pList[i++],(char*)Row[0],MAXDBNAME-1);
	}
pList[i][0]=0;
msqlFreeResult(Res);
msqlClose(sock);
return i;
}

int ZmSQLConnection::GetDBInfo(char* pServer,char* pDB,ZField** pInfo)
{
int sock,currfld=0,numcols;
m_row Row;
m_result *Res1,*Res2;
m_field* Field;

for(int i=0;i<MAXFLDLIST;i++)	
	pInfo[i]=NULL;
if((sock=msqlConnect(pServer))==-1)	
	return -1;
if(msqlSelectDB(sock,pDB)==-1)	{
	msqlClose(sock);
	return 0;
	}
if((Res1=msqlListTables(sock))==NULL)	{
	msqlClose(sock);
	return 0;
	}
while((Row=msqlFetchRow(Res1))!=NULL)	{
	if((Res2=msqlListFields(sock,(char*)Row[0]))==NULL)	{
		msqlFreeResult(Res1);
		msqlClose(sock);
		return 0;
		}
	numcols=msqlNumFields(Res2);
	while((Field=msqlFetchField(Res2))!=NULL)	{
		pInfo[currfld]=new ZField;
		if(!pInfo[currfld])	{
			msqlFreeResult(Res1);
			msqlFreeResult(Res2);
			msqlClose(sock);
			return currfld;
			}
		strncpy(pInfo[currfld]->Name,Field->name,MAXFLDNAME-1);
		strncpy(pInfo[currfld]->Table,Field->table,MAXFLDNAME-1);
		strncpy(pInfo[currfld]->FQFN,Field->table,MAXFLDNAME-1);
		strcat(pInfo[currfld]->FQFN,".");
		strncat(pInfo[currfld]->FQFN,Field->name,MAXFLDNAME-1);
		pInfo[currfld]->Length=Field->length;
		if(IS_NOT_NULL(Field->flags))
			pInfo[currfld]->Nullable=0;
		else
			pInfo[currfld]->Nullable=1;
		switch(Field->type)	{
			case INT_TYPE:
				pInfo[currfld]->Type=INT_FLD;
				break;
			case REAL_TYPE:
				pInfo[currfld]->Type=REAL_FLD;
				break;
			case CHAR_TYPE:
				pInfo[currfld]->Type=CHAR_FLD;
				break;
			default:
				pInfo[currfld]->Type=CHAR_FLD;
				break;
			}
		currfld++;
		}
	msqlFreeResult(Res2);
	}
msqlFreeResult(Res1);
msqlClose(sock);
return currfld;
}


//****************************************************************************
//				ShutDown
//****************************************************************************
void ZmSQLConnection::ShutDown()
{
if(!ConnectedToServer)
	return;
msqlClose(hDB);
Initialize();
}

//****************************************************************************
//				Initialize
//****************************************************************************
void ZmSQLConnection::Initialize()
{
ZDBConnection::Initialize();
Server[0]='\0';
DBName[0]='\0';
User[0]='\0';
Password[0]='\0';
ErrorMessage[0]='\0';
ConnectedToServer=FALSE;
ConnectedToDB=FALSE;
Type=MSQL_DB;
}

