#ifndef WSCDBPGSQL_H
#define WSCDBPGSQL_H

#ifdef MSW
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libpq-fe.h>

#include <WScom.h>
#include <WSCvariant.h>

struct _PgsqlCol {
	WSCuchar	colName[32];
	short		colType;
	int			buffLen;
	void*		buff;
};

#define PGSQL_ACCESS_MODE_READ			0
#define PGSQL_ACCESS_MODE_EDIT			1
#define PGSQL_ACCESS_MODE_ADDNEW		2
#define PGSQL_MAX_MESSAGE_LENGTH		255
#define PGSQL_TRAN_FUNCTION				1
#define PGSQL_TRAN_RECORD_FUNCTION		2

// PostgreSQL  pg_wchar.h
#ifndef PG_TYPE_BOOL
#define PG_TYPE_BOOL         16
#define PG_TYPE_BYTEA        17
#define PG_TYPE_CHAR         18
#define PG_TYPE_NAME         19
#define PG_TYPE_INT8         20
#define PG_TYPE_INT2         21
#define PG_TYPE_INT2VECTOR   22
#define PG_TYPE_INT4         23
#define PG_TYPE_REGPROC      24
#define PG_TYPE_TEXT         25
#define PG_TYPE_OID          26
#define PG_TYPE_TID          27
#define PG_TYPE_XID          28
#define PG_TYPE_CID          29
#define PG_TYPE_OIDVECTOR    30
#define PG_TYPE_SET          32
#define PG_TYPE_CHAR2       409
#define PG_TYPE_CHAR4       410
#define PG_TYPE_CHAR8       411
#define PG_TYPE_POINT       600
#define PG_TYPE_LSEG        601
#define PG_TYPE_PATH        602
#define PG_TYPE_BOX         603
#define PG_TYPE_POLYGON     604
#define PG_TYPE_FILENAME    605
#define PG_TYPE_FLOAT4      700
#define PG_TYPE_FLOAT8      701
#define PG_TYPE_ABSTIME     702
#define PG_TYPE_RELTIME     703
#define PG_TYPE_TINTERVAL   704
#define PG_TYPE_UNKNOWN     705
#define PG_TYPE_MONEY		790
#define PG_TYPE_OIDINT2     810
#define PG_TYPE_OIDINT4     910
#define PG_TYPE_OIDNAME     911
#define PG_TYPE_BPCHAR     1042
#define PG_TYPE_VARCHAR    1043
#define PG_TYPE_DATE       1082
#define PG_TYPE_TIME       1083
#define PG_TYPE_DATETIME   1184
#define PG_TYPE_TIMESTAMP  1296
#define PG_TYPE_NUMERIC    1700
#endif // PG_TYPE_BOOL

#ifndef EUC_JP
#define EUC_JP 1				/* EUC for Japanese */
#define EUC_CN 2				/* EUC for Chinese */
#define EUC_KR 3				/* EUC for Korean */
#define UNICODE 5				/* Unicode UTF-8 */
#define LATIN1 7				/* ISO-8859 Latin 1 */
#define LATIN2 8				/* ISO-8859 Latin 2 */
#define LATIN3 9				/* ISO-8859 Latin 3 */
#define LATIN4 10				/* ISO-8859 Latin 4 */
#define LATIN5 11				/* ISO-8859 Latin 5 */
#define LATIN6 12				/* ISO-8859 Latin 6 */
#define LATIN7 13				/* ISO-8859 Latin 7 */
#define LATIN8 14				/* ISO-8859 Latin 8 */
#define LATIN9 15				/* ISO-8859 Latin 9 */
#define KOI8   16				/* KOI8-R/U */
#define SJIS 32					/* Shift JIS */
#define BIG5 33					/* Big5 */
#endif // EUC_JP
////

#define IS_PGSQL_ERROR(a)											\
		(a == NULL ||												\
		 PQresultStatus((PGresult*)a) == PGRES_BAD_RESPONSE ||		\
		 PQresultStatus((PGresult*)a) == PGRES_NONFATAL_ERROR ||	\
		 PQresultStatus((PGresult*)a) == PGRES_FATAL_ERROR)


class WSCdbDrvDatabase;
class WSCdbDrvRecord;
class WSCdbPgsqlRecord;

class WSCdbPgsqlDatabase : public  WSCdbDrvDatabase
{
public:
	WSDLEX32 WSCdbPgsqlDatabase();
	WSDLEX32 virtual ~WSCdbPgsqlDatabase();
	
	WSDLEX32 virtual long     open(char* host, char* uid, char* pwd, char* dbname, char* port = NULL);
	WSDLEX32 virtual long     close();
	WSDLEX32 virtual long     beginTran();
	WSDLEX32 virtual long     commitTran();
	WSDLEX32 virtual long     abortTran();
	WSDLEX32 virtual long     sqlExecute(const char* stmt);
	WSDLEX32 virtual WSCbool  isOpen();
	WSDLEX32 virtual void     getErrorMsg(char* szState, char* szMsg);
	WSDLEX32 virtual void     getErrorMsg(char* szMsg,long size);
	WSDLEX32 virtual void    setEncode(long code);
	WSDLEX32 virtual long    getEncode();

	        WSDLEX32 int      getProcessId();
	        WSDLEX32 WSCulong getCursor();
	        WSDLEX32 short    getbeginTranmode();
	        WSDLEX32 void     setbeginTranmode(short begin);
	        WSDLEX32 char*    getDbName();
private:
	void    getError();
	void    encoding_conv(long code);
//	void    encode(char* buf, char* str);
	char*   decode(const char* buf);

public:
	WSCbool		_open;
	short		_begin;
	PGconn*		_hconn;
	WSCuchar	_szSqlState[6];
	WSCuchar	_szErrorMsg[PGSQL_MAX_MESSAGE_LENGTH + 1];
	WSCulong	_cursor;
	int			_processid;
	char		_dbName[80];
	long		_encoding;
};

class WSCdbPgsqlRecord  : public  WSCdbDrvRecord
{
public:
	WSDLEX32 WSCdbPgsqlRecord(WSCdbPgsqlDatabase* pDatabase);
	WSDLEX32 virtual ~WSCdbPgsqlRecord();
	WSDLEX32 virtual long    open(const char* stmt);
	WSDLEX32 virtual long    open(const char* stmt, short eCousor, short eAccess = WSCDB_SQL_CONCUR_LOCK);
	WSDLEX32 virtual long    close();
	WSDLEX32 virtual WSCbool isEOF();
	WSDLEX32 virtual WSCbool isOpen();
	WSDLEX32 virtual long    getColValue(long index, WSCvariant* var);
	WSDLEX32 virtual long    getColValue(const char* name, WSCvariant* var);
	WSDLEX32 virtual long    getColStringValue(long index, char* var);
	WSDLEX32 virtual long    getColStringValue(const char* name, char* var);
	WSDLEX32 virtual long    setColValue(long index, WSCvariant var);
	WSDLEX32 virtual long    setColValue(const char* name, WSCvariant var);
	WSDLEX32 virtual long    edit();
	WSDLEX32 virtual long    update();
	WSDLEX32 virtual long    addnew();
	WSDLEX32 virtual long    deleterow();
	WSDLEX32 virtual long    moveNext();
	WSDLEX32 virtual long    movePrevious();
	WSDLEX32 virtual long    moveFirst();
	WSDLEX32 virtual long    moveLast();
	WSDLEX32 virtual long    getColName(long index, char* name);
	WSDLEX32 virtual long    getColIndex(const char* name);
	WSDLEX32 virtual long    getColType(long index);
	WSDLEX32 virtual long    getColType(const char* name);
	WSDLEX32 virtual long    getColLength(long index);
	WSDLEX32 virtual long    getColLength(const char* name);
	WSDLEX32 virtual long    getRowCount();
	WSDLEX32 virtual long    getColCount();
	WSDLEX32 virtual void    getErrorMsg(char* szState, char* szMsg);
	WSDLEX32 virtual WSCstring getErrorMessage();
	WSDLEX32 virtual long    isNull(long index);
	WSDLEX32 virtual long    isNull(const char* name);

private:
	void  Cleanup(WSCdbPgsqlDatabase* pDatabase);
	long  BindCols();
	void  ReleaseCols();
	void  getValue(int index, WSCvariant* var);
	void  setValue(int index, WSCvariant* var);
	void  getError();
	char* makeINSERT();
	char* makeUPDATE();
	char* makeDELETE();
	void  getTableName(char* p, char* tbl, int size);
	long  setRowPos(WSCulong pos);
	int   getBufflen(int type);
	char* getSqlString(int i);
	void  encode(char* buf, char* str);
	char* decode(char* buf);
	long  getColTypeConv(long index);

public:
	WSCdbPgsqlDatabase*	_pDB;
	PGresult*			_res_stmt;
	WSCbool				_open;
	short				_Cols;
	_PgsqlCol*			_fd;
	short				_access_mode;
	WSCuchar			_szSqlState[6];
	WSCuchar			_szErrorMsg[PGSQL_MAX_MESSAGE_LENGTH + 1];
	int					_access;
	int					_Cursor;
	char				_CurrsorName[80];
	WSCulong			_RowCount;
	WSCulong			_FetchRowPos;
	long				_encoding;
	char				_tableName[80];
	int					_oiduse;
};

#endif		// WSCDBPGSQL_H
