#include <WSCdb.h>
#include <WSCdbDrv.h>
#include <WSCdbMysql.h>
#include <WSClocaleSet.h>

#include "udebug.h"

extern "C" {
void libwsmysql_func();
};
void libwsmysql_func(){
}

#ifdef FACTORY_METHOD /* factory method handler..*/
WSCdbDrvDatabase* _WSCdbMysqlDatabase_create_(){
  WSCdbMysqlDatabase* inst = new WSCdbMysqlDatabase();
  inst->setThisPtr(inst);
  return inst;
}
WSCdbDrvRecord* _WSCdbMysqlRecord_create_(WSCdbDrvDatabase* db){
  return new WSCdbMysqlRecord((WSCdbMysqlDatabase*)db->getThisPtr());
}

class _WSCdbMysqlDatabase_init_ {
  public:
    _WSCdbMysqlDatabase_init_ (){
       WSCdbDatabase::setCreateHandler((void*)_WSCdbMysqlDatabase_create_,"MYSQL");
       WSCdbRecord::setCreateHandler((void*)_WSCdbMysqlRecord_create_,"MYSQL");
    };
};
static _WSCdbMysqlDatabase_init_ _execute_initialize_;
#endif /* factory method handler..*/

WSCdbMysqlDatabase::WSCdbMysqlDatabase() : WSCdbDrvDatabase()
{
	TRACE_U(("WSCdbMysqlDatabase::WSCdbMysqlDatabase start"));
	
	_hconn = NULL;
	_open = False;
	_begin = 0;
	memset(_dbName, '\0', sizeof(_dbName));
	_encoding = -1;
	TRACE_U(("WSCdbMysqlDatabase::WSCdbMysqlDatabase end"));
}
WSCdbMysqlDatabase::~WSCdbMysqlDatabase()
{
	TRACE_U(("WSCdbMysqlDatabase::~WSCdbMysqlDatabase"));

	close();
	
	TRACE_U(("WSCdbMysqlDatabase::~WSCdbMysqlDatabase end"));
}

long WSCdbMysqlDatabase::open(char* host, char* uid, char* pwd, char* dbname, char* port)
{
	TRACE_U(("WSCdbMysqlDatabase::open start"));

	if(isOpen()) {
		close();
	}
	_open = False;
	
	if(!(_hconn = mysql_init((MYSQL*)0))) {
		return WS_ERR;
	}
	if(!mysql_real_connect(_hconn, 
						   host, 
						   (uid == NULL ? NULL : strlen(uid) == 0 ? NULL : uid), 
						   (pwd == NULL ? NULL : strlen(pwd) == 0 ? NULL : pwd), 
						   (dbname == NULL ? NULL : strlen(dbname) == 0 ? NULL : dbname),
						   (port == NULL ? 0 : strlen(port) == 0 ? 0 : atoi(port)),
						   NULL,
						   0)) {
		getError();
        return WS_ERR;
	}
	_open = True;
	if(dbname) {
		strcpy(_dbName, dbname);
	}
	getServerEncoding();

	TRACE_U(("WSCdbMysqlDatabase::open end"));
	return WS_NO_ERR;
}
long WSCdbMysqlDatabase::close()
{
	TRACE_U(("WSCdbMysqlDatabase::close start"));
	if(_hconn == NULL) {
		return WS_NO_ERR;
	}
	if(_begin) {
		abortTran();
	}
	mysql_close(_hconn);
	_hconn = NULL;
	_open = False;
	memset(_dbName, '\0', sizeof(_dbName));
	_encoding = -1;
	TRACE_U(("WSCdbMysqlDatabase::close end"));
	return WS_NO_ERR;
}
long WSCdbMysqlDatabase::beginTran()
{
	TRACE_U(("WSCdbMysqlDatabase::beginTran start"));
	if(!isOpen()) {
		return WS_ERR;
	}
	long ret = WS_NO_ERR;
	if(mysql_query(_hconn, "BEGIN")) {
		getError();
		ret = WS_ERR;
	}
	TRACE_U(("WSCdbMysqlDatabase::beginTran end"));
	return ret;
}
long WSCdbMysqlDatabase::commitTran()
{
	TRACE_U(("WSCdbMysqlDatabase::commitTran start"));
	if(!isOpen()) {
		return WS_ERR;
	}
	long ret = WS_NO_ERR;
	if(mysql_query(_hconn, "COMMIT")) {
		getError();
		ret = WS_ERR;
	} else {
		_begin = False;
	}
	TRACE_U(("WSCdbMysqlDatabase::commitTran end"));
	return ret;
}
long WSCdbMysqlDatabase::abortTran()
{
	TRACE_U(("WSCdbMysqlDatabase::abortTran start"));
	if(!isOpen()) {
		return WS_ERR;
	}
	long ret = WS_NO_ERR;
	if(mysql_query(_hconn, "ROLLBACK")) {
		getError();
		ret = WS_ERR;
	} else {
		_begin = False;
	}
	TRACE_U(("WSCdbMysqlDatabase::abortTran end"));
	return ret;
}
long WSCdbMysqlDatabase::sqlExecute(const char* stmt)
{
	TRACE_U(("WSCdbMysqlDatabase::sqlExecute start"));
	if(!isOpen()) {
		return WS_ERR;
	}
	long ret = WS_NO_ERR;
	if(mysql_query(_hconn, decode(stmt))) {
		getError();
		ret = WS_ERR;
	}
	TRACE_U(("WSCdbMysqlDatabase::sqlExecute end"));
	return ret;
}
WSCbool WSCdbMysqlDatabase::isOpen()
{
	return _open;
}
void WSCdbMysqlDatabase::getError()
{
	TRACE_U(("WSCdbMysqlDatabase::getError start"));

	sprintf((char*)_szSqlState, "%05d", mysql_errno(_hconn));
	memset(_szErrorMsg, '\0', sizeof(_szErrorMsg));
	strncpy((char*)_szErrorMsg, mysql_error(_hconn), sizeof(_szErrorMsg)-1);

	TRACE_U(("WSCdbMysqlDatabase::getError State:%s messgae:%s", _szSqlState, _szErrorMsg));
	TRACE_U(("WSCdbMysqlDatabase::getError end"));
}

void WSCdbMysqlDatabase::getErrorMsg(char* szState, char* szMsg)
{
	TRACE_U(("WSCdbMysqlDatabase::getErrorMsg start"));
	
	strcpy(szState, (char*)_szSqlState);
	strcpy(szMsg, (char*)_szErrorMsg);
	
	TRACE_U(("WSCdbMysqlDatabase::getErrorMsg end"));
}

void WSCdbMysqlDatabase::getErrorMsg(char* szMsg,long size)
{
	TRACE_U(("WSCdbMysqlDatabase::getErrorMsg start"));
	
	char szStat[6];
	char szErrorMsg[MYSQL_MAX_MESSAGE_LENGTH + 1];
	char buf[MYSQL_MAX_MESSAGE_LENGTH + 1+32];
	getErrorMsg(szStat,szErrorMsg);
	sprintf(buf,"status:%s message:%s",szStat,szErrorMsg);
	strncpy(szMsg,buf,size);
	szMsg[size] = '\0';

	TRACE_U(("WSCdbMysqlDatabase::getErrorMsg end"));
}
int WSCdbMysqlDatabase::getProcessId()
{
	return 0;
}
WSCulong WSCdbMysqlDatabase::getCursor()
{
	return 0;
}
short WSCdbMysqlDatabase::getbeginTranmode()
{
	return _begin;
}
void WSCdbMysqlDatabase::setbeginTranmode(short begin)
{
	_begin = begin;
}
char* WSCdbMysqlDatabase::getDbName()
{
	return _dbName;
}
void WSCdbMysqlDatabase::setEncode(long code)
{
	_encoding = code;
}
long WSCdbMysqlDatabase::getEncode()
{
	return _encoding;
}
void WSCdbMysqlDatabase::getServerEncoding()
{
	if(mysql_query(_hconn, "show variables")) {
		_encoding = -1;
		return;
	}
	MYSQL_RES*	res = mysql_store_result(_hconn);
	WSCulong RowCount = (unsigned long)mysql_num_rows(res);
	char code[80];
	code[0] = '\0';
	for(WSCulong i = 0; i < RowCount; i++) {
		mysql_data_seek(res, i);
		MYSQL_ROW row = mysql_fetch_row(res);
		if(WSGFstricmp(row[0], "character_set") == 0) {
			strcpy(code, row[1]);
			break;
		}
	}
	mysql_free_result(res);

	if(WSGFstricmp(code, "latin1") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "big5") == 0) {
		_encoding = WS_EN_BIG5;
	} else
	if(WSGFstricmp(code, "czech") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "euc_kr") == 0) {
		_encoding = WS_EN_EUCKR;
	} else
	if(WSGFstricmp(code, "gb2312") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "gbk") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "sjis") == 0) {
		_encoding = WS_EN_SJIS;
	} else
	if(WSGFstricmp(code, "tis620") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "ujis") == 0) {
		_encoding = WS_EN_EUCJP;
	} else
	if(WSGFstricmp(code, "dec8") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "dos") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "german1") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "hp8") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "koi8_ru") == 0) {
		_encoding = WS_EN_KOI8R;
	} else
	if(WSGFstricmp(code, "latin2") == 0) {
		_encoding = WS_EN_ISO8859_2;
	} else
	if(WSGFstricmp(code, "swe7") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "usa7") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "cp1251") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "danish") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "hebrew") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "win1251") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "estonia") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "hungarian") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "koi8_ukr") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "win1251ukr") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "greek") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "win1250") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "croat") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "cp1257") == 0) {
		_encoding = -1;
	} else
	if(WSGFstricmp(code, "latin5") == 0) {
		_encoding = WS_EN_ISO8859_5;
	} else {
		_encoding = -1;
	}
	TRACE_U(("getServerEncoding code:%s, _encoding:%d\n", code, _encoding));
}
char* WSCdbMysqlDatabase::decode(const char* buf)
{
	long decode = WSGIappLocaleSet()->getDefaultEncoding();
	static WSCstring s;
	s = buf;
	if(_encoding != decode && _encoding != -1) {
	TRACE_U(("decode buf:%s\n", buf));
	TRACE_U(("decode str:%s\n", s.getString(_encoding)));
		return s.getString(_encoding);
	}
	return s.getString();
}

/////
WSCdbMysqlRecord::WSCdbMysqlRecord(WSCdbMysqlDatabase* pDatabase) : WSCdbDrvRecord(pDatabase)
{
	TRACE_U(("WSCdbMysqlRecord::WSCdbMysqlRecord start"));

	Cleanup(pDatabase);

	TRACE_U(("WSCdbMysqlRecord::WSCdbMysqlRecord end"));
}
void WSCdbMysqlRecord::Cleanup(WSCdbMysqlDatabase* pDatabase)
{
	_pDB = pDatabase;
	_res_stmt = NULL;
	_open = False;
	_Cols = 0;
	_fd = NULL;
	_access_mode = MYSQL_ACCESS_MODE_READ;
	_Cursor = WSCDB_SQL_CURSOR_STATIC;
	_access = WSCDB_SQL_CONCUR_LOCK;
	memset(_szSqlState, '\0', sizeof(_szSqlState));
	memset(_szErrorMsg, '\0', sizeof(_szErrorMsg));
	_RowCount = 0;
	_FetchRowPos = 0;
	_encoding = -1;
	_rowiduse = 0;
}

WSCdbMysqlRecord::~WSCdbMysqlRecord()
{
	TRACE_U(("WSCdbMysqlRecord::~WSCdbMysqlRecord start"));

	close();

	_pDB = NULL;

	TRACE_U(("WSCdbMysqlRecord::~WSCdbMysqlRecord end"));
}
long WSCdbMysqlRecord::open(const char* stmt)
{
	return open(stmt, WSCDB_SQL_CURSOR_STATIC, WSCDB_SQL_CONCUR_LOCK);
}
long WSCdbMysqlRecord::open(const char* stmt, short eCousor, short eAccess)
{
	TRACE_U(("WSCdbMysqlRecord::open start"));

	if(_pDB == NULL) {
		return WS_ERR;
	}
	if(_pDB->_hconn == NULL) {
		return WS_ERR;
	}
	if(isOpen()) {
		close();
	}
	_open = False;
	_Cursor = eCousor;
	_access = eAccess;
	_RowCount = 0;
	_FetchRowPos = 0xffffffff;
	_encoding = _pDB->getEncode();;
	_rowiduse = 0;
	
	long ret = WS_NO_ERR;
	char*	buf;
	char	buf1[256];
	strncpy(buf1, stmt, 6);
	buf1[6] = '\0';

	if(_access != WSCDB_SQL_CONCUR_READ_ONLY 
		&& WSGFstricmp(buf1, "select") == 0) {
		getTableName((char*)stmt, _tableName, sizeof(_tableName));

		sprintf(buf1, "select _rowid from %s", _tableName);
		if(mysql_query(_pDB->_hconn, buf1)) {
			_rowiduse = 0;
			TRACE_U(("WSCdbMysqlRecord::open rowid not use"));
		} else {
			_rowiduse = 1;
			TRACE_U(("WSCdbMysqlRecord::open rowid use"));
			_res_stmt = mysql_store_result(_pDB->_hconn);
			mysql_free_result(_res_stmt);
		}
	} else {
		_rowiduse = 0;
	}
	buf = getSelectSQL(stmt, _rowiduse);

	int res = mysql_query(_pDB->_hconn, buf);
	delete[] buf;
	
	if(res) {
		getError();
		ret = WS_ERR;
	} else {
		_res_stmt = mysql_store_result(_pDB->_hconn);
		_RowCount = (unsigned long)mysql_num_rows(_res_stmt);
		if(BindCols() != WS_NO_ERR) {
			return WS_ERR;
		}
	}
	_open = True;

	moveNext();

	TRACE_U(("WSCdbMysqlRecord::open end"));
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::close()
{
	TRACE_U(("WSCdbMysqlRecord::close start"));
	
	if(_res_stmt) {
		mysql_free_result(_res_stmt);
	}
	_res_stmt = NULL;
	ReleaseCols();
	_open = False;
	_RowCount = 0;
	_FetchRowPos = 0;
	_encoding = -1;
	_rowiduse = 0;
	
	TRACE_U(("WSCdbMysqlRecord::close end"));
	return WS_NO_ERR;
}
WSCbool WSCdbMysqlRecord::isEOF()
{
	return (_FetchRowPos < _RowCount ? False : True);
}
WSCbool WSCdbMysqlRecord::isOpen()
{
	return _open;
}
long WSCdbMysqlRecord::getColValue(long index, WSCvariant* var)
{
	if(index < 0 || index >= (_Cols-_rowiduse)) {
		return WS_ERR;
	}
	getValue(index, var);
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::getColValue(const char* name, WSCvariant* var)
{
	return getColValue(getColIndex(name), var);
}
long WSCdbMysqlRecord::getColStringValue(long index, char* var)
{
	if(index < 0 || index >= (_Cols-_rowiduse)) {
		return WS_ERR;
	}
	strcpy(var, (char*)_fd[index].buff);
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::getColStringValue(const char* name, char* var)
{
	return getColStringValue(getColIndex(name), var);
}
long WSCdbMysqlRecord::setColValue(long index, WSCvariant var)
{
	if(index < 0 || index >= (_Cols-_rowiduse)) {
		return WS_ERR;
	}
	if(_access_mode == MYSQL_ACCESS_MODE_READ || _rowiduse == 0) {
		return WS_ERR;
	}
	setValue(index, &var);
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::setColValue(const char* name, WSCvariant var)
{
	return setColValue(getColIndex(name), var);
}
long WSCdbMysqlRecord::edit()
{
	if(isEOF() || _access == WSCDB_SQL_CONCUR_READ_ONLY || _rowiduse == 0) {
		return WS_ERR;
	}
	_access_mode = MYSQL_ACCESS_MODE_EDIT;
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::addnew()
{
	if(!isOpen() || _access == WSCDB_SQL_CONCUR_READ_ONLY || _rowiduse == 0) {
		return WS_ERR;
	}
	for(int i = 0; i < _Cols; i++) {
		memset(_fd[i].buff, '\0', _fd[i].buffLen);
	}
	_access_mode = MYSQL_ACCESS_MODE_ADDNEW;
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::update()
{
	long ret = WS_ERR;
	if(_access_mode == MYSQL_ACCESS_MODE_ADDNEW) {
		ret = _pDB->sqlExecute(makeINSERT());
	} else
	if(_access_mode == MYSQL_ACCESS_MODE_EDIT) {
		ret = _pDB->sqlExecute(makeUPDATE());
	}
	_access_mode = MYSQL_ACCESS_MODE_READ;
	return ret;
}
long WSCdbMysqlRecord::deleterow()
{
	if(isEOF() || _access == WSCDB_SQL_CONCUR_READ_ONLY || _rowiduse == 0) {
		return WS_ERR;
	}
	_access_mode = MYSQL_ACCESS_MODE_READ;
	return _pDB->sqlExecute(makeDELETE());
}
long WSCdbMysqlRecord::moveNext()
{
	_access_mode = MYSQL_ACCESS_MODE_READ;

	if(_FetchRowPos != 0xffffffff) {
		if(isEOF()) {
			return WS_ERR;
		}
	}
	_FetchRowPos++;
	if(isEOF()) {
		return WS_ERR;
	}
	return setRowPos(_FetchRowPos);
}
long WSCdbMysqlRecord::movePrevious()
{
	if(!isOpen()) {
		return WS_ERR;
	}
	_access_mode = MYSQL_ACCESS_MODE_READ;
	return setRowPos((_FetchRowPos > 0 ? --_FetchRowPos : 0));
}
long WSCdbMysqlRecord::moveFirst()
{
	if(!isOpen()) {
		return WS_ERR;
	}
	_access_mode = MYSQL_ACCESS_MODE_READ;
	return setRowPos(0);
}
long WSCdbMysqlRecord::moveLast()
{
	if(isEOF()) {
		return WS_ERR;
	}
	_access_mode = MYSQL_ACCESS_MODE_READ;
	return setRowPos(_RowCount-1);
}
long WSCdbMysqlRecord::setRowPos(WSCulong pos)
{
	_FetchRowPos = pos;
	mysql_data_seek(_res_stmt, _FetchRowPos);
	MYSQL_ROW row = mysql_fetch_row(_res_stmt);
	for(int i = 0; i < _Cols; i++) {
		encode(row[i], (char*)_fd[i].buff);
	}
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::getColName(long index, char* name)
{
	if(!isOpen()) {
		return -1;
	}
	if(index < 0 || index >= (_Cols-_rowiduse)) {
		return WS_ERR;
	}
	strcpy(name, (char*)_fd[index].colName);
	return WS_NO_ERR;
}
long WSCdbMysqlRecord::getColIndex(const char* name)
{
	if(!isOpen()) {
		return -1;
	}
	for(int i = 0; i < (_Cols-_rowiduse); i++) {
		if(WSGFstricmp((char*)_fd[i].colName, (char*)name) == 0) {
			return (i);
		}
	}
	return -1;
}
long WSCdbMysqlRecord::getColType(long index)
{
	if(!isOpen()) {
		return -1;
	}
	if(index < 0 || index >= (_Cols-_rowiduse)) {
		return -1;
	}
//	return _fd[index].colType;
	return getColTypeConv(index);

}
long WSCdbMysqlRecord::getColType(const char* name)
{
	return getColType(getColIndex(name));
}
long WSCdbMysqlRecord::getColLength(long index)
{
	if(!isOpen()) {
		return -1;
	}
	if(index < 0 || index >= (_Cols-_rowiduse)) {
		return -1;
	}
	return _fd[index].buffLen-1;
}
long WSCdbMysqlRecord::getColLength(const char* name)
{
	return getColType(getColIndex(name));
}

long WSCdbMysqlRecord::getRowCount()
{
	return (isOpen() ? _RowCount : 0);
}
long WSCdbMysqlRecord::getColCount()
{
	return _Cols-_rowiduse;
}
long WSCdbMysqlRecord::BindCols()
{
	TRACE_U(("WSCdbMysqlRecord::BindCols start"));

	_Cols = mysql_num_fields(_res_stmt);
	if(_Cols < 1) {
		TRACE_U(("WSCdbMysqlRecord::BindCols PQnfields() Error"));
		getError();
		return WS_ERR;
	}
	_fd = new _MysqlCol[_Cols];
	memset(_fd, '\0', sizeof(_MysqlCol) * _Cols);
	MYSQL_FIELD* fd = mysql_fetch_fields(_res_stmt);
	for(int i = 0; i < _Cols; i++ ) {
 		strncpy((char*)_fd[i].colName, fd[i].name, sizeof(_fd[i].colName)-1);
		_fd[i].colType = fd[i].type;
		if(_fd[i].colType == FIELD_TYPE_STRING) {
			_fd[i].buffLen = fd[i].length + 1;
		}
		if(_fd[i].buffLen < 1) {
			_fd[i].buffLen = getBufflen(fd[i].type);
		}
		_fd[i].buff = new char[_fd[i].buffLen];
		memset(_fd[i].buff, '\0', _fd[i].buffLen);
	}

	TRACE_U(("WSCdbMysqlRecord::BindCols end"));
	return WS_NO_ERR;
}
void WSCdbMysqlRecord::ReleaseCols()
{
	TRACE_U(("WSCdbMysqlRecord::ReleaseCols start"));
	
	if(_fd == NULL) {
		return;
	}
    for(int i = 0; i < _Cols; i++ ) {
        delete[] (char*)(_fd[i].buff);
    }
    delete[] _fd;

	_fd = NULL;

	TRACE_U(("WSCdbMysqlRecord::ReleaseCols end"));
}

void WSCdbMysqlRecord::getValue(int index, WSCvariant* var)
{
	TRACE_U(("WSCdbMysqlRecord::getValue start"));
	TRACE_U(("WSCdbMysqlRecord::getValue _fd[index].colType:%d", _fd[index].colType));

	if(_fd[index].colType == FIELD_TYPE_STRING) {
		// SQL_CHAR unsigned char
		*var = (char*)_fd[index].buff;
	} else
	if(_fd[index].colType == FIELD_TYPE_DECIMAL) {
		// SQL_NUMERIC, SQL_DECIMAL
		*var = (char*)_fd[index].buff;
	} else
	if(_fd[index].colType == FIELD_TYPE_LONG) {
		// SQL_INTEGER long int
		*var = (long)atol((char*)_fd[index].buff);
	} else
	if(_fd[index].colType == FIELD_TYPE_SHORT) {
		// SQL_SMALLINT short int
		*var = (short)atoi((char*)_fd[index].buff);
	} else
	if(_fd[index].colType == FIELD_TYPE_DOUBLE) {
		// SQL_FLOAT, SQL_DOUBLE float
		*var = (double)atof((char*)_fd[index].buff);
	} else
	if(_fd[index].colType == FIELD_TYPE_FLOAT) {
		// SQL_REAL REAL
		*var = (float)atof((char*)_fd[index].buff);
	} else
	if(_fd[index].colType == FIELD_TYPE_DATE) {
		// SQL_TYPE_DATE
		*var = (char*)_fd[index].buff;
	} else
	if(_fd[index].colType == FIELD_TYPE_TIME) {
		// SQL_TYPE_TIME
		*var = (char*)_fd[index].buff;
	} else
	if(_fd[index].colType == FIELD_TYPE_DATETIME) {
		// SQL_TYPE_TIMESTAMP
		*var = (char*)_fd[index].buff;
	} else {
		*var = (char*)_fd[index].buff;
	}

	TRACE_U(("WSCdbMysqlRecord::getValue end"));
}
void WSCdbMysqlRecord::setValue(int index, WSCvariant* var)
{
	TRACE_U(("WSCdbMysqlRecord::setValue start"));
	TRACE_U(("WSCdbMysqlRecord::setValue _fd[index].colType:%d", _fd[index].colType));

	int len = (int)strlen((char*)var);

	if(_fd[index].colType == FIELD_TYPE_STRING) {
		// SQL_CHAR unsigned char
		strncpy((char*)_fd[index].buff, (char*)var, _fd[index].buffLen-1);
		((char*)_fd[index].buff)[(len < _fd[index].buffLen ? len : _fd[index].buffLen-1)] = '\0';
	} else
	if(_fd[index].colType == FIELD_TYPE_DECIMAL) {
		// SQL_NUMERIC, SQL_DECIMAL
		strncpy((char*)_fd[index].buff, (char*)var, _fd[index].buffLen-1);
		((char*)_fd[index].buff)[(len < _fd[index].buffLen ? len : _fd[index].buffLen-1)] = '\0';
	} else
	if(_fd[index].colType == FIELD_TYPE_LONG) {
		// SQL_INTEGER long int
		sprintf((char*)_fd[index].buff, "%d", var->getLong());
	} else
	if(_fd[index].colType == FIELD_TYPE_SHORT) {
		// SQL_SMALLINT short int
		sprintf((char*)_fd[index].buff, "%d", var->getShort());
	} else
	if(_fd[index].colType == FIELD_TYPE_DOUBLE) {
		// SQL_FLOAT, SQL_DOUBLE float
		sprintf((char*)_fd[index].buff, "%f", var->getDouble());
	} else
	if(_fd[index].colType == FIELD_TYPE_FLOAT) {
		// SQL_REAL REAL
		sprintf((char*)_fd[index].buff, "%f", var->getFloat());
	} else
	if(_fd[index].colType == FIELD_TYPE_DATE) {
		// SQL_TYPE_DATE
		strncpy((char*)_fd[index].buff, (char*)var, _fd[index].buffLen-1);
		((char*)_fd[index].buff)[(len < _fd[index].buffLen ? len : _fd[index].buffLen-1)] = '\0';
	} else
	if(_fd[index].colType == FIELD_TYPE_TIME) {
		// SQL_TYPE_TIME
		strncpy((char*)_fd[index].buff, (char*)var, _fd[index].buffLen-1);
		((char*)_fd[index].buff)[(len < _fd[index].buffLen ? len : _fd[index].buffLen-1)] = '\0';
	} else
	if(_fd[index].colType == FIELD_TYPE_DATETIME) {
		// SQL_TYPE_TIMESTAMP
		strncpy((char*)_fd[index].buff, (char*)var, _fd[index].buffLen-1);
		((char*)_fd[index].buff)[(len < _fd[index].buffLen ? len : _fd[index].buffLen-1)] = '\0';
	} else {
		strncpy((char*)_fd[index].buff, (char*)var, _fd[index].buffLen-1);
		((char*)_fd[index].buff)[(len < _fd[index].buffLen ? len : _fd[index].buffLen-1)] = '\0';
	}

	TRACE_U(("WSCdbMysqlRecord::setValue end"));
}

void WSCdbMysqlRecord::getError()
{
	TRACE_U(("WSCdbMysqlRecord::getError start"));

	sprintf((char*)_szSqlState, "%05d", mysql_errno(_pDB->_hconn));
	memset(_szErrorMsg, '\0', sizeof(_szErrorMsg));
	strncpy((char*)_szErrorMsg, mysql_error(_pDB->_hconn), sizeof(_szErrorMsg)-1);

	TRACE_U(("WSCdbMysqlRecord::getError State:%s messgae:%s", _szSqlState, _szErrorMsg));
	TRACE_U(("WSCdbMysqlRecord::getError end"));
}

void WSCdbMysqlRecord::getErrorMsg(char* szState, char* szMsg)
{
	TRACE_U(("WSCdbMysqlRecord::getErrorMsg start"));

	strcpy(szState, (char*)_szSqlState);
	strcpy(szMsg, (char*)_szErrorMsg);

	TRACE_U(("WSCdbMysqlRecord::getErrorMsg start"));
}
char* WSCdbMysqlRecord::makeINSERT()
{
	static WSCstring str;
	str = "insert into ";
	str << _tableName;
	str << "(";
	int i;
	for(i = 0; i < _Cols-1; i++) {
		str << (char*)_fd[i].colName;
		if(i < _Cols-2) {
			str << ",";
		}
	}
	str << ") values(";
	for(i = 0; i < _Cols-1; i++) {
		str << getSqlString(i);
		if(i < _Cols-2) {
			str << ",";
		}
	}
	str << ")";
	TRACE_U(("makeINSERT:%s", str.getString()));
	return str.getString();
}
char* WSCdbMysqlRecord::makeUPDATE()
{
	static WSCstring str;

	str = "update ";
	str << _tableName;
	str << " set ";
	for(int i = 0; i < _Cols-1; i++) {
		str << (char*)_fd[i].colName;
		str << "=";
		str << getSqlString(i);
		if(i < _Cols-2) {
			str << ",";
		}
	}
	str << " where _rowid = ";
	str << (char*)_fd[0].buff;
	TRACE_U(("makeUPDATE:%s", str.getString()));
	return str.getString();
}
char*  WSCdbMysqlRecord::makeDELETE()
{
	static WSCstring str;

	str = "delete from ";
	str << _tableName;
	str << " where _rowid = ";
	str << (char*)_fd[_Cols-1].buff;
	TRACE_U(("makeDELETE:%s", str.getString()));
	return str.getString();
}

void WSCdbMysqlRecord::getTableName(char* p, char* tbl, int size)
{
	char buf[7];
	buf[6] = '\0';
	*tbl = '\0';
	for(; *p != '\0'; p++) {
		if(*p != ' ') {
			continue;
		}
		strncpy(buf, p, 6);
		if(WSGFstricmp(buf, " FROM ") == 0) {
			int j = 0;
			char* s1 = p + 6;
			for(j = 0; (*s1 != '\0') &&  j < size; s1++) {
				if(*s1 == ' ') {
					if(tbl[0] != '\0') {
						tbl[j] = '\0';
						break;
					}
//				} else {
				} else if(*s1 != '(' && *s1 != ')') {
					tbl[j++] = *s1;
				}
			}
			break;
		}
	}
}
int WSCdbMysqlRecord::getBufflen(int type)
{
	if(type == FIELD_TYPE_STRING) {
		return 32767;
	} else
	if(type == FIELD_TYPE_DECIMAL) {
		// SQL_NUMERIC, SQL_DECIMAL
		return 11 + 1;
	} else 
	if(type == FIELD_TYPE_LONG) {
		// SQL_INTEGER long int
		return 11 + 1;
	} else
	if(type == FIELD_TYPE_SHORT) {
		// SQL_SMALLINT short int
		return 6 + 1;
	} else
	if(type == FIELD_TYPE_DOUBLE) {
		// SQL_FLOAT, SQL_DOUBLE float
		return 22 + 1;
	} else
	if(type == FIELD_TYPE_FLOAT) {
		// SQL_REAL REAL
		return 13 + 1;
	} else
	if(type == FIELD_TYPE_DATE) {
		// SQL_TYPE_DATE
		return 10 + 1;
	} else
	if(type == FIELD_TYPE_TIME) {
		// SQL_TYPE_TIME
		return 23 + 1;
	} else
	if(type == FIELD_TYPE_DATETIME) {
		// SQL_TYPE_TIMESTAMP:
		return 23 + 1;
	}
	return 32767;
}
char* WSCdbMysqlRecord::getSqlString(int i)
{
	static WSCstring str;
	str = "";
	
	if(_fd[i].colType == FIELD_TYPE_DECIMAL) {
		str << (char*)_fd[i].buff;
	} else
	if(_fd[i].colType == FIELD_TYPE_LONG) {
		str << (char*)_fd[i].buff;
	} else
	if(_fd[i].colType == FIELD_TYPE_SHORT) {
		str << (char*)_fd[i].buff;
	} else
	if(_fd[i].colType == FIELD_TYPE_DOUBLE) {
		str << (char*)_fd[i].buff;
	} else
	if(_fd[i].colType == FIELD_TYPE_FLOAT) {
		str << (char*)_fd[i].buff;
	} else {
		str << "'" << decode((char*)_fd[i].buff) << "'";
	}
	return str.getString();
}
void WSCdbMysqlRecord::encode(char* buf, char* str)
{
	long encode = WSGIappLocaleSet()->getDefaultEncoding();
	if(_encoding != encode && _encoding != -1) {
		WSCstring s(buf,  _encoding);
		strcpy(str, s.getString(encode));
	TRACE_U(("encode buf:%s\n", buf));
	TRACE_U(("encode str:%s\n", str));
	} else {
		strcpy(str, buf);
	}
}
char* WSCdbMysqlRecord::decode(char* buf)
{
	long decode = WSGIappLocaleSet()->getDefaultEncoding();
	static WSCstring s;
	s = buf;
	if(_encoding != decode && _encoding != -1) {
	TRACE_U(("decode buf:%s\n", buf));
	TRACE_U(("decode str:%s\n", s.getString(_encoding)));
		return s.getString(_encoding);
	}
	return s.getString();
}
char* WSCdbMysqlRecord::getSelectSQL(const char* p, long rowiduse)
{
	char* buf = new char[strlen(p) + 256];
	char  buf1[7];
	char  buf2[256];
	buf1[6] = '\0';
	if(rowiduse == 1) {
		for(int i = 0; *p != '\0'; p++, i++) {
			if(*p == ' ') {
				strncpy(buf1, p, 6);
				if(WSGFstricmp(buf1, " FROM ") == 0) {
//					strcpy(&buf[i], ",_rowid as _rowid_rowuse_");
					sprintf(buf2, ",%s._rowid as _rowid_rowuse_", _tableName);
					strcpy(&buf[i], buf2);
					strcat(buf, p);
					break;
				}
			}
			buf[i] = *p;
		}
	} else {
		strcpy(buf, p);
	}
	return buf;
}
long WSCdbMysqlRecord::getColTypeConv(long index)
{
	if(_fd[index].colType == FIELD_TYPE_STRING) {
		return WSCDB_FIELD_TYPE_CHAR;
	} else
	if(_fd[index].colType == FIELD_TYPE_DECIMAL) {
		// SQL_NUMERIC, SQL_DECIMAL
		return WSCDB_FIELD_TYPE_DECIMAL;
	} else 
	if(_fd[index].colType == FIELD_TYPE_LONG) {
		// SQL_INTEGER long int
		return WSCDB_FIELD_TYPE_INTEGER;
	} else
	if(_fd[index].colType == FIELD_TYPE_SHORT) {
		// SQL_SMALLINT short int
		return WSCDB_FIELD_TYPE_SMALLINT;
	} else
	if(_fd[index].colType == FIELD_TYPE_DOUBLE) {
		// SQL_FLOAT, SQL_DOUBLE float
		return WSCDB_FIELD_TYPE_DOUBLE;
	} else
	if(_fd[index].colType == FIELD_TYPE_FLOAT) {
		// SQL_REAL REAL
		return WSCDB_FIELD_TYPE_REAL;
	} else
	if(_fd[index].colType == FIELD_TYPE_DATE) {
		// SQL_TYPE_DATE
		return WSCDB_FIELD_TYPE_DATE;
	} else
	if(_fd[index].colType == FIELD_TYPE_TIME) {
		// SQL_TYPE_TIME
		return WSCDB_FIELD_TYPE_TIME;
	} else
	if(_fd[index].colType == FIELD_TYPE_DATETIME) {
		// SQL_TYPE_TIMESTAMP:
		return WSCDB_FIELD_TYPE_TIMESTAMP;
	}
	return WSCDB_FIELD_TYPE_NONE;
}
WSCstring WSCdbMysqlRecord::getErrorMessage()
{
  WSCstring ret;
  char stat[10];
  char buf[MYSQL_MAX_MESSAGE_LENGTH+1];
  getErrorMsg(stat,buf);
  char buf2[MYSQL_MAX_MESSAGE_LENGTH+1+32];
  sprintf(buf2,"state: %s ,message: %s",stat,buf);
  ret.setString(buf2);
  return ret;
}
