`
wooce
  • 浏览: 184146 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Progress商业数据库的访问接口的C++包装

阅读更多
iprogressdb.h:

/*      Written by Wooce                     Date: 2002-04        */

#ifndef _IPROGRESSDB_H
#define _IPROGRESSDB_H

#include "idbbase.h"
#include "idbbasetype.h"
#include "sql_lib.h"
#include "ilist.h"
#include "idatetime.h"

typedef void * tpe_cursor_type;
extern int g_ProgressType[DBType_OTHER+1];

class IProgressConnection;
class IProgressStatement;

//--------------------------IProgressCheckErr-------------------------------------

class IProgressCheckErr
{
public:
	IProgressCheckErr(void) {}
	~IProgressCheckErr(void) {}

	static bool    CheckErr(struct sqlca& SQLca);
	static int		CheckErr(struct sqlca& SQLca,IString & res);
	static void	CheckErrEx(struct sqlca& SQLca);
};

//--------------------------End of IProgressCheckErr-------------------------------


class IProgressEnvironment : public IDBEnvironment
{
public:
	IProgressEnvironment(int mode = 0);	//
	~IProgressEnvironment(void) {}

	ISTDDBConnection* GetConnection(const char * lpszDBName,const char * lpszUser,const char * lpszPassword,const char * ip,const char * port=NULL);
};

//-------------------------------------------------------------------------

class IProgressConnection : public ISTDDBConnection
{
protected:
       	IProgressEnvironment	*	m_pEnv;
	struct sqlca sqlca;
	bool	m_bConnected;
	IString m_strConName;
public:
	//Constructor
	IProgressConnection(IProgressEnvironment * pEnv = NULL);
	//Destructor
	~IProgressConnection(void) {Close();}

        void TranCommit(bool boDistributed);
        void TranRollBack(void);
	struct sqlca *	GetSQLCA(void) {return &sqlca;}

	//Standard Interface
	void	Close(void);
	int		Connect(const char * lpszDBName,const char * lpszUser,const char * lpszPassword,const char * ip,const char * lpszPort=NULL);

	ISTDDBStatement *	GetStatement(const IString & strSQL = "");
	ISTDDBStatement *	GetTableList(const IString & strLikeWild = "");
	bool	IsConnected(void);
	IString	EncodeString(const IString & strSrc);
};

//---------------------------------------------------------------------
class IProgressStatement : public ISTDDBStatement
{
private:
protected:
	IProgressCheckErr Check;
	IProgressConnection   *	m_pConnection;
	int					    m_nInfoCount;
	ISTDColumnInfo	      * m_pInfo;

	IString				    m_strSQL;

	tpe_cursor_type         m_cursor;
	pro_sqlda             * m_pSQLDA;
	dh_i32_t              * m_pIVARPTR;

	IDWORD				    m_dwRowCount;

	void				ClearColInfo(void);
	void				GetColumnInfo(void);
	ISTDField	*		NewField(ISTDColumnInfo & info);

	void		ValueByName(const char * lpszFieldName,ISTDField * param);
	void		ValueByPos(int nPos,ISTDField * param);

	void		ParamByName(const char * lpszParamName,ISTDField * param);
	void		ParamByPos(int nPos,ISTDField * param);
public:
	IProgressStatement(IProgressConnection * pConnection = NULL);
	~IProgressStatement(void) {Close();}

	void		Use(IProgressConnection	* pConnection);
	void		Close(void);

	void		Prepare(const IString & strSQL);
        void            PrepareParam(const IString & strSQL);

	bool		Exec(bool boCommit = false);
	bool		ExecCommit(void);
	bool		ExecAndSelectLastInsert(const IString & strTableName,const IString & strAutoIncField,bool boCommit = false);

	ISTDColumnInfo & GetColumnInfo(int nPos);
	IDWORD		GetRowCount(void);

	bool		Fetch(void);
	IString		InsertID(void);
};


#endif

iprogressdb.cpp:

/*      Written by Wooce                     Date: 2002-04        */

#ifdef _HAS_PROGRESS

	#include "iprogressdb.h"
	#include "iprogresstype.h"
	#include "idbbasetype.h"
	#include "istring.h"
	#include "sql_lib.h"
	#include <ctype.h>

int g_ProgressType[DBType_OTHER+1] =
{							 //						Maximum Internal Length			Type of Program variable
	dnu_TPE_DT_ERR,			 //
	dnu_TPE_DT_TINYINT,		 // TinyInt                 1 byte							char
	dnu_TPE_DT_SMALLINT,	 // SmallInt				2 bytes							short
	0,						 // Unsigned int						                    unsigned
	dnu_TPE_DT_INTEGER,		 // INTEGER 				4/2/1 Byte						int/long/short
	dnu_TPE_DT_BIGINT,		 // LONGLONG                Fix size:						sizeof(long long)
	dnu_TPE_DT_REAL,		 // FLOAT                   sizeof(float)                                       float
	dnu_TPE_DT_FLOAT,		 // DOUBLE                  sizeof(double)					double
	dnu_TPE_DT_NUMERIC,		 // NUMBER
	dnu_TPE_DT_NUMERIC,		 // VARNUM
	0,						 // LONG                    2^31-1 Byte						char[n]
	dnu_TPE_DT_CHAR,		 // CHAR
	dnu_TPE_DT_VARCHAR,				 // VARCHAR2
	dnu_TPE_DT_VARCHAR,		 // CHARZ
	dnu_TPE_DT_LVC,			 // Nullterminated STRING Null Terminated STRING			char[n+1]
	dnu_TPE_DT_VARCHAR,		 // VARCHAR												    char[n+sizeof(short int)]
	dnu_TPE_DT_VARCHAR,		 // LONG VARCHAR											char[n+sizeof(int)]
	dnu_TPE_DT_BINARY,		 // RAW					    2000 Byte					    unsigned char[n]
	dnu_TPE_DT_BINARY,		 // LONG RAW				2^31-1 Byte						unsigned char[n]
	dnu_TPE_DT_VARBINARY,	 // VARRAW												    unsigned char[n+sizeof(short int)]
	dnu_TPE_DT_LVB,			 // LONG VARRAW											    unsigned char[n+sizeof(int)]
	0,						 // DATETIME
	dnu_TPE_DT_DATE,		 // DATE
	dnu_TPE_DT_TIME,		 // TIME
	dnu_TPE_DT_TIMESTAMP,	 // TIMESTAMP
	dnu_TPE_DT_LVB,			 // Character LOB			~4000
	dnu_TPE_DT_LVB,			 // Binary LOB			    ~4000
	0,
	0,
	0x7fffffff
};

//-----------------------------------------------------------

bool IProgressCheckErr::CheckErr(struct sqlca& pSQLCA)
{
	if( pSQLCA.sqlcode<0 )
		return true;
	else
		return false;
}

int IProgressCheckErr::CheckErr(struct sqlca& pSQLCA,IString & res)
{
	if( pSQLCA.sqlcode<0 )
	{
		res.Format("Progress : Error - (%d) %s",pSQLCA.sqlcode,pSQLCA.sqlerrm);
		return pSQLCA.sqlcode;
	} else
	{
		res = "Progress : NORMAL";
		return NORMAL;
	}
}

void IProgressCheckErr::CheckErrEx(struct sqlca& pSQLCA)
{
	IString res;
	int retcode = CheckErr(pSQLCA,res);
	if(retcode!=NORMAL)
		throw(ISTDDBException(ERR_SQL_ERR,"%s",res.CConstStr()));
}

//-----------------------------------------------------------

IProgressEnvironment::IProgressEnvironment(int mode)
{
	for(int i=0;i<DBType_OTHER+1;i++)
		m_DBType[i] = g_ProgressType[i];
}

ISTDDBConnection* IProgressEnvironment::GetConnection(const char * lpszDBName,const char * lpszUser,const char * lpszPassword,const char * ip,const char * port)
{
	IDBConnection con(new IProgressConnection(this));
	if(con.Get() == NULL)
		throw(ISTDDBException(MEMNOTENOUGH,"GetConnetion:no mem"));
	con->Connect(lpszDBName,lpszUser,lpszPassword,ip,port);
	return con.Release();
}

//-------------------------------------------------------------------------

IProgressConnection::IProgressConnection(IProgressEnvironment * pEnv)
: ISTDDBConnection(DB_SUPPORT_NOSELECT_ROWCOUNT|DB_SUPPORT_TRANSACTION),
m_pEnv(pEnv),m_bConnected(false)
{
}

void IProgressConnection::Close(void)
{
	if(m_bConnected)
	{
		struct sqlca ca;
		tpe_sql_disconnect(SQL_DISCONNECT_CONNECTION,(char *)m_strConName.CConstStr(),&ca);
		m_bConnected = false;
	}
}

void IProgressConnection::TranCommit(bool boDistributed)
{
	if(m_pEnv == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Commit:not init env"));
	struct sqlca ca;
	tpe_tm_end_trans(tpe_get_curtmhdl(),&ca);
	IProgressCheckErr::CheckErrEx(ca);
}

void IProgressConnection::TranRollBack(void)
{
	if(m_pEnv == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Rollback:not init env"));
	struct sqlca ca;
	tpe_tm_mark_abort(tpe_get_curtmhdl(),&ca);
	IProgressCheckErr::CheckErrEx(ca);
	tpe_tm_end_trans(tpe_get_curtmhdl(),&ca);
	IProgressCheckErr::CheckErrEx(ca);
}

int IProgressConnection::Connect(const char * lpszDBName,const char * lpszUser,const char * lpszPassword,const char * ip,const char * lpszPort)
{
	if( IsConnected() )
		Close();
	IString connectStr;
	connectStr.Format("progress:T:%s:%s:%s",ip,lpszPort,lpszDBName);
	struct sqlca ca;
	m_strConName = connectStr;
	IDateTime dt;
	dt.SetCurTime();
	m_strConName += IntToStr( (long long)dt.GetTime() );
	tpe_sqlconnect(connectStr.CConstStr(),m_strConName.CConstStr(),lpszUser,lpszPassword,(dh_char_t *)0,&ca); 
	IProgressCheckErr::CheckErrEx(ca);
	m_bConnected = true;
	return NORMAL;
}

bool IProgressConnection::IsConnected(void)
{
	if(!m_bConnected)
		return false;
	struct sqlca ca;
	tpe_sql_chk_connection(&ca);
	if(ca.sqlcode < 0)
		return false;
	else
		return true;
}

ISTDDBStatement * IProgressConnection::GetStatement(const IString & strSQL)
{
	IDBStatement statement(new IProgressStatement(this));
	if(statement.Get() == NULL)
		throw(ISTDDBException(MEMNOTENOUGH,"GetStatement:no mem"));
	if(!strSQL.IsEmpty())
		statement->Prepare(strSQL);
	return statement.Release();
}

ISTDDBStatement * IProgressConnection::GetTableList(const IString & strLikeWild)
{
	IString strSQL;
	if(strLikeWild.IsEmpty())
		strSQL = "select tbl from sysprogress.systables";
	else
		strSQL.Format("select tbl from sysprogress.systables where tbl like '%s'",EncodeString(strLikeWild).CConstStr());
	IDBStatement statement(new IProgressStatement(this));
	if(statement.Get() == NULL)
		throw(ISTDDBException(MEMNOTENOUGH,"GetStatement:no mem"));
	statement->Exec(strSQL);
	return statement.Release();
}

IString IProgressConnection::EncodeString(const IString & strSrc)
{
	IString res;
	for(const unsigned char * tp = (const unsigned char *)strSrc.CConstStr();*tp!='\0';tp++)
	{
		if(*tp == '\'')	res += (char)'\'';
		res += (char)(*tp);
	}
	return res;
}

//---------------------------------------------------------------------
IProgressStatement::IProgressStatement(IProgressConnection * pConnection)
: ISTDDBStatement(),m_pConnection(pConnection),m_nInfoCount(0),
m_pInfo(NULL),m_cursor(NULL),m_dwRowCount(0),m_pSQLDA(NULL),m_pIVARPTR(NULL)
{
}

void IProgressStatement::ClearColInfo(void)
{
	if(m_nInfoCount > 0 && m_pInfo!=NULL)
		delete []m_pInfo;
	if(m_pIVARPTR!=NULL)
		delete m_pIVARPTR;
	m_nInfoCount = 0;
	m_pInfo = NULL;
}

//  be called in destructor and Prepare(const IString & strSQL) function
void IProgressStatement::Close(void)
{
	if(m_pConnection == NULL)
		return;
	ClearColInfo();
	struct sqlca ca;
	struct sqlca * pSQLCA = &ca;
	tpe_sqlclose(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor,pSQLCA);	//关闭光标
	if( m_pSQLDA!=NULL )
		PRO_SQLDA_Deallocate(m_pSQLDA);
	m_dwRowCount = 0;
	ISTDDBStatement::Close();
}

void IProgressStatement::Use(IProgressConnection * pConnection)
{
	Close();
	m_pConnection = pConnection;
}

void IProgressStatement::Prepare(const IString & strSQL)
{
	if(m_pConnection == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Prepare:not init env"));
	Close();
	m_strSQL = strSQL;
	m_strSQL.LTrim();
	struct sqlca *pSQLCA = m_pConnection->GetSQLCA();
	dh_char_t *sqlcmd = (char *)strSQL.CConstStr();
	static tpe_uuid__t tpe_uuid = {0x3cad7190, 0x4b97, 0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
	tpe_set_cursor(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type *)&m_cursor,&tpe_uuid,1,sqlcmd,pSQLCA);
	Check.CheckErrEx(*pSQLCA);
	tpe_set_cursorname(m_cursor,NULL,pSQLCA);
	Check.CheckErrEx(*pSQLCA);
	tpe_sqlprepare(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor, pSQLCA);
	PrepareParam(m_strSQL);
}

void IProgressStatement::PrepareParam(const IString & strSQL)
{
	int nParamCount = 0,i;
	ClearParams();

	if(strSQL.Find(':') >= 0)
	{
		const char * tp = strSQL.CConstStr();
		nParamCount = 0;
		while(*tp!='\0')	//Count the number
		{
			if(*tp==':') nParamCount++;
			else if(*tp=='\'')
			{
				tp++;
				while((*tp!='\'' || *(tp-1)=='\\') && *tp!='\0') tp++;
				if(*tp=='\0') break;
			}
			tp ++;
		}
		if(nParamCount>0)
		{
			struct sqlca ca;
			struct sqlca* SQLCAPTR = &ca;
			if( m_pSQLDA==NULL )
				m_pSQLDA = PRO_SQLDA_Allocate(3,20);
			if( m_pSQLDA==NULL )
				throw ISTDDBException(MEMNOTENOUGH,"GetColumnInfo:no mem");
			for(;;)
			{
				dh_u32_t desiredCols;
				tpe_sqldescribe_param(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor,m_pSQLDA,&ca);
				PRO_SQLDA_Get_DA_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_DA_ATTR_DESIREDCOLS,&desiredCols,SQLCAPTR);
				if( desiredCols>0 )
				{
					PRO_SQLDA_Deallocate(m_pSQLDA);
					m_pSQLDA = PRO_SQLDA_Allocate(desiredCols,20);
					if( m_pSQLDA==NULL )
						throw ISTDDBException(MEMNOTENOUGH,"GetColumnInfo:no mem");
					continue;
				}
				break;
			}                        
			dh_u32_t numCols;
			PRO_SQLDA_Get_DA_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_DA_ATTR_ACTUALCOLS,&numCols,&ca);
			if( numCols!=nParamCount )	   //手工代码检出的param数目和tpe_sqldescribe_param不同? 
				throw ISTDDBException(ERR_PROGRESS_ERROR,"Error with getting input params of sql statement:%s",strSQL.CConstStr());
			m_nParamCount = nParamCount;
			m_ppParams = new ISTDField * [nParamCount];
			if(m_ppParams ==NULL)
				throw(ISTDDBException(MEMNOTENOUGH,"Prepare statement Param:no mem"));

			for(i=0;i<nParamCount;i++) m_ppParams[i] = NULL;

			tp = strSQL.CConstStr();
			i = 0;
			while(*tp!='\0')	//Count the number
			{
				if(*tp==':')
				{
					int len =0;
					tp++;
					while(*tp!='\0' && strchr(" ;,:\t\n\r()",*tp)==NULL)
					{
						len++; tp++;
					}
					m_ppParams[i] = NewParam();
					ParamByPos(i,m_ppParams[i]);
					m_ppParams[i++]->SetFieldName(IString(tp-len,len));
					if(*tp=='\0') break;
				} else if(*tp=='\'')
				{
					tp++;
					while((*tp!='\'' || *(tp-1)=='\\') && *tp!='\0') tp++;
					if(*tp=='\0') break;
				}
				tp ++;
			}
		}
	}
}

void IProgressStatement::ParamByName(const char * lpszParamName,ISTDField * param)
{
	if(m_pConnection == NULL || m_strSQL.IsEmpty())
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Param:not init env or prepare sql"));
	for( int i=0;i<m_nParamCount;i++ )
		if( m_ppParams[i++]->GetFieldName().ICompare(lpszParamName)==0 )
		{
			ParamByPos(i,param);
			return;
		}
	throw ISTDDBException(ERR_PROGRESS_ERROR,"not exists this param in dynamic sql statement:%s",lpszParamName);
}

void IProgressStatement::ParamByPos(int nPos,ISTDField * param)
{
	if(m_pConnection == NULL || m_strSQL.IsEmpty())
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Param:not init env or prepare sql"));
	struct sqlca ca;
	PRO_SQLDA_Set_Col_Attribute_void_p(m_pSQLDA,PRO_SQLDA_COL_ATTR_VARPTR,nPos+1,param->GetOriginalAddress(),&ca);
	PRO_SQLDA_Set_Col_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_COL_ATTR_LENGTH,nPos+1,param->GetElementLen()+1,&ca);	  // maybe no need?
}

bool IProgressStatement::ExecCommit(void)
{
	return Exec(true);
}

// exec a sql statement
bool IProgressStatement::Exec(bool boCommit)
{
	if(m_pConnection == NULL || m_strSQL.IsEmpty())
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Exec:not init env or prepare sql"));
	if(!m_pConnection->IsConnected())
		throw(ISTDDBException(ERR_SQL_ERR,"Exec:not init env or prepare sql"));
	ClearColInfo();
	ClearValues();
	struct sqlca *pSQLca = m_pConnection->GetSQLCA();

	if( m_strSQL.INCompare("select",6)==0 )
	{
		tpe_sqlopen(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor, (struct sqlda *)0, pSQLca);
		Check.CheckErrEx(*pSQLca);
		GetColumnInfo();
		PrepareValue();
	} else
	{
		m_dwRowCount = 0;
		tpe_sqlexecute(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor,(struct sqlda *)0,pSQLca);
		Check.CheckErrEx(*pSQLca);
		/*if( pSQLca->sqlcode==SQL_NOT_FOUND )
			throw ISTDDBException(ERR_SQL_ERR,"Exec: Requested row not found!"); */
		m_dwRowCount += (IDWORD)pSQLca->sqlerrd[2];		 //affected rows
		if( boCommit )
		{
			struct sqlca ca;
			tpe_tm_end_trans(tpe_get_curtmhdl(),&ca);
			Check.CheckErrEx(ca);
		}
	}
	return true;
}

void IProgressStatement::GetColumnInfo(void)
{
	if( m_cursor==NULL )
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"GetColumnInfo:no cursor"));

	struct sqlca *SQLCAPTR = m_pConnection->GetSQLCA();
	//    allocate SQLDA for tpe_sqldescribe output
	if( m_pSQLDA==NULL )
		m_pSQLDA = PRO_SQLDA_Allocate(3,20);
	if( m_pSQLDA==NULL )
		throw ISTDDBException(MEMNOTENOUGH,"GetColumnInfo:no mem");
	for(;;)
	{
		dh_u32_t desiredCols;
		tpe_sqldescribe(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor,m_pSQLDA,SQLCAPTR);
		PRO_SQLDA_Get_DA_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_DA_ATTR_DESIREDCOLS,&desiredCols,SQLCAPTR);
		if( desiredCols>0 )
		{
			PRO_SQLDA_Deallocate(m_pSQLDA);
			m_pSQLDA = PRO_SQLDA_Allocate(desiredCols,20);
			if( m_pSQLDA==NULL )
				throw ISTDDBException(MEMNOTENOUGH,"GetColumnInfo:no mem");
			continue;
		}
		break;
	}
	Check.CheckErrEx(*SQLCAPTR);
	dh_u32_t numCols;
	PRO_SQLDA_Get_DA_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_DA_ATTR_ACTUALCOLS,&numCols,SQLCAPTR);
	Check.CheckErrEx(*SQLCAPTR);
	m_nInfoCount = numCols;
	if(m_nInfoCount <= 0)
		return;
	m_nColCount = m_nInfoCount;
	m_pInfo = new ISTDColumnInfo[m_nInfoCount];
	if(m_pInfo == NULL)
		throw(ISTDDBException(MEMNOTENOUGH,"GetColumnInfo:no mem"));
	dh_i16_t nmsize;
	PRO_SQLDA_Get_DA_Attribute_dh_i16_t(m_pSQLDA,PRO_SQLDA_DA_ATTR_VARNMSIZE,&nmsize,SQLCAPTR);
	Check.CheckErrEx(*SQLCAPTR);
	dh_char_t *col_name = new dh_char_t[nmsize];
	if(col_name == NULL)
		throw(ISTDDBException(MEMNOTENOUGH,"GetColumnInfo:no mem"));
	IAuto_Ptr<dh_char_t> autoColName(col_name);
	m_pIVARPTR = new dh_i32_t[m_nInfoCount];
	if(m_pIVARPTR == NULL)
		throw(ISTDDBException(MEMNOTENOUGH,"GetColumnInfo:no mem"));
	for(int i=0;i<m_nInfoCount;i++)
	{
		//length
		dh_u32_t col_length;
		PRO_SQLDA_Get_Col_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_COL_ATTR_LENGTH,i+1,&col_length,SQLCAPTR);
		m_pInfo[i].m_dwElementLen = col_length;	//if character data,  col_length includes space for the trailing 0 character
		//type
		dh_i32_t col_type;
		PRO_SQLDA_Get_Col_Attribute_dh_i32_t(m_pSQLDA,PRO_SQLDA_COL_ATTR_DATATYPE,i+1,&col_type,SQLCAPTR);
		int j;
		switch(col_type)
		{
		case dnu_TPE_DT_INTEGER:
			j = DBType_INTEGER; break;
		case dnu_TPE_DT_SMALLINT:
			j = DBType_SMALLINT; break;
		case dnu_TPE_DT_TINYINT:
		case dnu_TPE_DT_BIT:
			j = DBType_TINYINT; break;

		case dnu_TPE_DT_BIGINT:
			j = DBType_LONGLONG; break;

		case dnu_TPE_DT_NUMERIC:
			j = DBType_DECIMAL; break;

		case dnu_TPE_DT_REAL:
			j = DBType_FLOAT;break;
		case dnu_TPE_DT_FLOAT:
			j = DBType_DOUBLE; break;

		case dnu_TPE_DT_CHAR:
			j = DBType_CHAR; break;
		case dnu_TPE_DT_VARCHAR:
			j = DBType_VARCHAR; break;

		case dnu_TPE_DT_TIMESTAMP:
			j = DBType_TIMESTAMP; break;
		case dnu_TPE_DT_DATE:
			j = DBType_DATE; break;
		case dnu_TPE_DT_TIME:
			j = DBType_TIME; break;

		case dnu_TPE_DT_BINARY:
			j = DBType_BINARY; break;
		case dnu_TPE_DT_VARBINARY:
			j = DBType_VARBINARY; break;
		case dnu_TPE_DT_LVB:
			j = DBType_LONGVARBINARY; break;

		default:
			j = DBType_NTSTRING; break;
		}
		m_pInfo[i].m_nType = (DBSTDTYPE)j;
		//Name
		PRO_SQLDA_Get_Col_Attribute_dh_char_t_p(m_pSQLDA,PRO_SQLDA_COL_ATTR_VARNAME,i+1,&col_name,SQLCAPTR);
		m_pInfo[i].m_strName = col_name;
		//Flags
		dh_u32_t flags;
		PRO_SQLDA_Get_Col_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_COL_ATTR_FLAGS,i+1,&flags,SQLCAPTR);
		if( flags!=P_SQL_NO_NULLS )
			m_pInfo[i].m_nFlags = (DB_COLUMN_FLAGS)(m_pInfo[i].m_nFlags | DB_COLUMN_CANNULL);
		dh_u32_t odbcflags;
		PRO_SQLDA_Get_Col_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_COL_ATTR_ODBCFLAGS,i+1,&odbcflags,SQLCAPTR);
		/*  deprecated
		if( odbcflags&ITEM_AUTO )
			m_pInfo[i].m_nFlags = (DB_COLUMN_FLAGS)(m_pInfo[i].m_nFlags | DB_COLUMN_AUTO_INCREMENT);
			*/
		if( !(odbcflags&ITEM_SIGN) )
			m_pInfo[i].m_nFlags = (DB_COLUMN_FLAGS)(m_pInfo[i].m_nFlags | DB_COLUMN_UNSIGNED);
		PRO_SQLDA_Set_Col_Attribute_dh_i32_t_p(m_pSQLDA,PRO_SQLDA_COL_ATTR_IVARPTR,i+1,&(m_pIVARPTR[i]),SQLCAPTR);
	}
	autoColName.Release();
}

ISTDColumnInfo & IProgressStatement::GetColumnInfo(int nPos)
{
	if(m_pConnection == NULL || !m_pConnection->IsConnected())
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"GetColumnInfo:Not Init"));
	if(m_pInfo == NULL)
		GetColumnInfo();
	if(m_pInfo==NULL || nPos >= m_nColCount)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"GetColumnInfo:Out of range"));
	return m_pInfo[nPos];
}

//  can only get the affected row count of UPDATE,INSERT,DELETE, if you need to get the row count of the SELECT result,please use "select count(*)"
IDWORD IProgressStatement::GetRowCount(void)
{
	return m_dwRowCount;
}

// it's called in PrepareValue() in ISTDDBStatement
void IProgressStatement::ValueByPos(int nPos,ISTDField * param)
{
	if(m_pConnection == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"ValueByPos:Not Init"));
	struct sqlca *ca = m_pConnection->GetSQLCA();
	void *p = (void *)param->GetOriginalAddress();
	PRO_SQLDA_Set_Col_Attribute_void_p(m_pSQLDA,PRO_SQLDA_COL_ATTR_VARPTR,nPos+1,p,ca);
	Check.CheckErrEx(*ca);
}

void IProgressStatement::ValueByName(const char * lpszFieldName,ISTDField * param)
{
	if(m_pConnection == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"ValueByName:Not Init"));
	if(m_nInfoCount<0)
		GetColumnInfo();
	for(int i = 0;i<m_nInfoCount;i++)
		if(m_pInfo[i].m_strName.ICompare(lpszFieldName)==0)
		{
			ValueByPos(i,param);
			return;
		}
}

bool IProgressStatement::Fetch(void)
{
	if(m_pConnection == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Fetch:Not Init"));
	if(m_nColCount==0)
		return false;
	if(m_nColCount > 0 && m_pInfo == NULL)
		GetColumnInfo();
	if(m_ppFields==NULL)
		return false;

	struct sqlca *pSQLCA = m_pConnection->GetSQLCA();
	tpe_sqlfetch(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor,m_pSQLDA,pSQLCA);
	if( Check.CheckErr(*pSQLCA) )
	{
		if(!m_pConnection->IsConnected())
			throw(ISTDDBException(ERR_SQL_ERR,"Fetch: Not Connect"));
	}
	if( pSQLCA->sqlcode==SQL_NOT_FOUND )
	{
		return false;
	}
	for(int j=0;j<m_nColCount;j++)
		if(m_ppFields[j]!=NULL)
		{
			dh_i32_t* ivar;
			PRO_SQLDA_Get_Col_Attribute_dh_i32_t_p(m_pSQLDA,PRO_SQLDA_COL_ATTR_IVARPTR,j+1,&ivar,pSQLCA);
			if( *ivar<0 )	//NULL Column
			{
				m_ppFields[j]->AssignString("");           
				m_ppFields[j]->SetNULL();
			} else
				if( *ivar==0 )	 //Column data ok!
			{
				m_ppFields[j]->SetNormal();
				dh_u32_t length;
				PRO_SQLDA_Get_Col_Attribute_dh_u32_t(m_pSQLDA,PRO_SQLDA_COL_ATTR_LENGTH,j+1,&length,pSQLCA);
				m_ppFields[j]->SetFieldLen(length + 1);			  // ?
			} else
				throw ISTDDBException(ERR_SQL_ERR,"No room to hold column data!");
		}
	return true;
}

//  Get the id generated from the previous INSERT operation 
//  Progress don't have the corresponding function
IString IProgressStatement::InsertID(void)
{
	if(m_pConnection == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Fetch:Not Init"));
	struct sqlca ca;   // output of sqlfetchrid
	tpe_sqlfetchrid(tpe_get_curtmhdl(),tpe_get_curdbhdl(),(tpe_cursor_type)m_cursor,m_pSQLDA,m_pSQLDA,&ca);
	return "";
}

bool IProgressStatement::ExecAndSelectLastInsert(const IString & strTableName,const IString & /*strAutoIncField*/,bool boCommit)
{
	if(m_pConnection == NULL)
		throw(ISTDDBException(ERR_PROGRESS_ERROR,"Insert ID:not init"));
	/*if(m_strSQL.INCompare("insert ",7) != 0)
		return false;
	Exec(boCommit);
	IString strSQL;
	LONGLONG nID = (m_pConnection->GetHandle());
	if(nID == 0)
		return false;
	strSQL.Format("select * from %s where %s=%ld",
				  strTableName.CConstStr(),
				  strAutoIncField.CConstStr(),
				  nID);
	Prepare(strSQL);
	Exec(boCommit); */
	return true;
}

//  new an ISTDField object to adopt on column from the sql result
ISTDField * IProgressStatement::NewField(ISTDColumnInfo & info)
{
	ISTDField * tp = NULL;
	switch(info.m_nType)
	{
	case DBType_ROWID:
		tp = new IDBString(20); break;
	case DBType_TINYINT:
		tp = new IDBTinyInt();  break;
	case DBType_SMALLINT:
		tp = new IDBSmallInt();  break;
	case DBType_UNSIGNEDINT:
	case DBType_INTEGER:
		tp = new IDBInteger();  break;
	case DBType_LONGLONG:
		tp = new IDBLongLong(); break;
	case DBType_FLOAT:
		tp = new IDBFloat(); break;
	case DBType_DOUBLE:
		tp = new IDBDouble();
		break;
	case DBType_DECIMAL:
	case DBType_VARDECIMAL:
		tp = new IProgressDecimal(); break;
	case DBType_NTSTRING:
	case DBType_LONGCHAR:
	case DBType_CHAR:
	case DBType_CHARZ:
		tp = new IDBString(info.m_dwElementLen); break;
	case DBType_VARCHAR:
	case DBType_LONGVARCHAR:
		tp = new IDBVarStreamField(info.m_dwElementLen); break;		   // should not use IDBVarChar, for IDBVarChar use the first short int to contain the length, while Progress just return the flat string
	case DBType_BINARY:
	case DBType_VARBINARY:
		tp = new IProgressBinary(); break;
	case DBType_LONGVARBINARY:
		tp = new IDBLongVarBinary(info.m_dwElementLen); break;				 //  ?
	case DBType_DATETIME:
		tp = new IProgressTimeStamp(); break;
	case DBType_TIME:
		tp = new IProgressTime(); break;
	case DBType_DATE:
		tp = new IProgressDate(); break;
	case DBType_TIMESTAMP:
		tp = new IProgressTimeStamp(); break;
	case DBType_CLOB:
	case DBType_BLOB:
	case DBType_FILE:
	case DBType_OBJECT:
	default:
		break;
	}
	if(tp!=NULL)
	{
		tp->SetFieldName(info.m_strName);
		tp->SetFlags(info.m_nFlags);
	} else
		throw(ISTDDBException(MEMNOTENOUGH,"New Field:no mem"));
	return tp;
}

#endif
分享到:
评论

相关推荐

    PROGRESS win64位ODBC连接器/驱动

    ODBC是微软开发的一种标准接口,它允许应用程序通过统一的方式访问各种不同类型的数据库,包括Progress数据库。 描述中提到的“支持win64位”,意味着这个ODBC驱动是专为64位版本的Windows操作系统设计的。由于64位...

    Visual C++2010开发权威指南(共三部分).part1.rar

    5.7 Visual C++ 2010 Progress控件简介与开发 219 5.7.1 进度控件的样式 219 5.7.2 进度控件的设置 219 5.7.3 操作进度控件 220 5.8 Visual C++ 2010 Tree控件简介与开发 220 5.8.1 树控件样式 221 5.8.2 树控件父项...

    版本,升级,德慧V15工具

    "ntwdblib.dll"是SQL Server的数据库访问接口,通常用于连接和操作SQL Server数据库。在升级过程中,它可能用于处理与SQL Server数据库相关的更新。 "pbmss90.dll"可能是Progress OpenEdge的多用户服务支持组件,...

    VC++pbni测试程序源文件,可以作为pbni上手的初步工程

    它允许开发者利用C++或.NET语言的强大功能与Progress数据库进行交互,实现跨平台的数据访问和业务逻辑处理。 在提供的"VC++ pbni测试程序源文件"中,我们可以看到几个关键的文件,这些文件构成了一个简单的PBNI应用...

    VC++2010权威开发指南+源代码

     5.7 Visual C++ 2010 Progress控件简介与开发 219  5.7.1 进度控件的样式 219  5.7.2 进度控件的设置 219  5.7.3 操作进度控件 220  5.8 Visual C++ 2010 Tree控件简介与开发 220  5.8.1 树控件样式 221  ...

    postgresql odbc

    ODBC是一种标准的API,允许不同类型的数据库系统被多种编程语言访问,如C++、Python、Java等。在Windows环境中,有64位和32位两种版本的PostgreSQL ODBC驱动,以适应不同操作系统架构的应用需求。 标题中的...

    VC++2010权威开发指南+源代码.part2

     5.7 Visual C++ 2010 Progress控件简介与开发 219  5.7.1 进度控件的样式 219  5.7.2 进度控件的设置 219  5.7.3 操作进度控件 220  5.8 Visual C++ 2010 Tree控件简介与开发 220  5.8.1 树控件样式 221  ...

    dll.zip_C Builder_PB .net_pb webserver

    标题 "dll.zip_C++ Builder_PB .net_pb webserver" 暗示了这是一个与C++ Builder、Progress PB(PowerBuilder)以及.NET Framework相关的压缩包,主要用于在使用Web服务器时提供必要的DLL动态链接库文件。...

    Actuate Query 产品详细介绍.pdf

    7. **JDBC/ODBC**:Actuate iServer能够通过这些标准数据库连接接口,连接到各种数据库,如Oracle、Microsoft SQL Server、Sybase和Progress,进行数据检索和分析。 8. **APIs**:Actuate提供了丰富的API,包括...

    计算机软件-编程源码-PBNI开发指南PB9的英文PDF文档.zip

    PBNI,全称为Progressive Binary Network Interface,是Progress软件公司为PowerBuilder(PB)开发者提供的一种接口技术。这个“PBNI开发指南PB9的英文PDF文档”是针对PowerBuilder 9(PB9)版本的详细指导,旨在...

    Datatools科脉软件导入数据工具

    9. **pbodb90.dll**: 最后,这可能是一个数据库访问组件,用于连接和操作数据库,比如将导入的数据写入科脉软件的后台数据库。 综上所述,Datatools科脉软件导入数据工具是一个综合性的解决方案,它结合了多种技术...

    Android面试题集合(含答案).docx

    - **ContentProvider**: 提供统一的数据访问接口,跨应用数据共享。 - **网络存储**: 通过API等方式远程存储数据。 7. **启动Activity并返回数据**: - **startActivityForResult()**: 启动新Activity并指定请求...

    AutoCAD ObjectARX二次开发实例-状态栏上进度条、模式对话框.rar

    ObjectARX基于C++编程语言,它提供了丰富的API(应用程序编程接口),可以访问AutoCAD的内部数据结构和函数,创建动态链接库(DLL),在AutoCAD运行时加载和执行。通过ObjectARX,开发者可以创建定制的图元、命令、...

    JMS与ActiveMQ

    就像JDBC允许我们与各种数据库进行交互一样,JMS提供了一种与供应商无关的方式来访问消息传递系统。这意味着开发者可以使用JMS API与IBM的MQSeries、BEA的Weblogic JMS service、Progress的SonicMQ等不同厂商的消息...

    Android开发案例驱动教程 配套代码

    10.5 编写访问SQLite数据库组件 220 10.5.1 DBHelper类 220 10.5.2 数据插入 222 10.5.3 数据删除 224 10.5.4 数据修改 224 10.5.5 数据查询 227 10.6 案例重构 229 10.6.1 系统架构设计 229 10.6.2 重构...

    安卓部分面试题总结

    - **final 和 const**:final 表示不可变,const 在 C++ 中用于定义常量。 #### 21. HTTP 网络接口设计 - **定义通用接口**:如 GET、POST 方法,支持参数传递。 - **示例接口**: ```java public interface ...

Global site tag (gtag.js) - Google Analytics