#include "DCUDB.h"
#include "rmdb.h"
#include <string.h>
#include <stdlib.h>
#include <set>
int SplitConnStr(const char * szConnStr, char * szUser, char * szPwd, char * szServer)
{
if(!szConnStr || !szUser || !szPwd || !szServer)
{
return -1;
}
const char * pos1 = strchr(szConnStr, '/');
if(!pos1)
{
return -1;
}
const char * pos2 = strchr(pos1, '@');
if(!pos2)
{
return -1;
}
strncpy(szUser, szConnStr, pos1-szConnStr);
szUser[pos1-szConnStr] = 0x0;
strncpy(szPwd, pos1+1, pos2-pos1-1);
szPwd[pos2-pos1-1] = 0x0;
strcpy(szServer, pos2+1);
return 0;
}
inline UDBSTATE CheckOraDBConnected(int sqlcode)
{
static int db_codes[]={
28, /* ORA-00028: 会话己被删去 */
1012, /* ORA-01012: 没有登录 */
1089, /* ORA-01089: 正在进行紧急关闭 - 不允许进行任何操作 */
3135, /* ORA-03135:连接断开 */
3113, /* ORA-03113: 通信通道关闭 */
3114, /* ORA-03114:没有连接到oracle */
12170, /* ORA-12170: 连接超时 */
12541, /* ORA-12541:没有监听器 */
12560 /* ORA-12560:协议适配错误 */
};
for(int i = 0; i < int(sizeof(db_codes)/sizeof(int)); i++)
{
if(sqlcode == db_codes[i])
{
return UDBS_DB_UNLINK; /* 连接失效,需重连 */
}
}
return UDBS_NONE;
}
inline UDBSTATE CheckOraStmtConnected(int sqlcode)
{
static int stmt_codes[]={
70, /* ORA00070: command is not valid */
};
for(int i = 0; i < int(sizeof(stmt_codes)/sizeof(int)); i++)
{
if(sqlcode == stmt_codes[i])
{
return UDBS_STMT_INVALID; /* SQL失效,需重置 */
}
}
return CheckOraDBConnected(sqlcode);
}
/*----------------------------------------------------------------------------*/
class UDBRMDBConnectionImp: public UDBConnection
{
public:
UDBRMDBConnectionImp(const char* category, const char* name , const char* version)
:UDBConnection(category, name, version)
,m_state(UDBS_NONE)
,m_sql(NULL)
{
m_imp = new DCRMDBConnection();
}
virtual ~UDBRMDBConnectionImp()
{
delete m_sql;
delete m_imp;
}
virtual int Connect(const char* str, const char* env = 0)
{
char szUser[80]={0};
char szPwd[80]={0};
char szServer[80]={0};
try
{
m_scon = str;
SplitConnStr(str, szUser, szPwd, szServer);
m_imp->Connect(szServer, szUser, szPwd);
m_state = UDBS_DB_LINK;
}
catch(DCRMDBException& e)
{
m_state = UDBS_DB_UNLINK;
throw UDBException(e.GetErrorCode(), e.GetErrorInfo(), e.GetSqlErrorCode(), e.GetSqlErrorInfo(), e.GetSqlState());
}
return 0;
}
virtual int Destroy()
{
delete m_sql;
m_sql = NULL;
return m_imp->Release();
}
virtual int Reset(const char* str = 0)
{
int ret = -1;
char szUser[80]={0};
char szPwd[80]={0};
char szServer[80]={0};
try
{
delete m_sql;
m_sql = NULL;
if(!str || m_scon == str)
{
ret = m_imp->Reset();
}
else
{
m_scon = str;
SplitConnStr(str, szUser, szPwd, szServer);
m_imp->Release();
ret = m_imp->Connect(szServer, szUser, szPwd);
}
if(!ret)
{
ResetSQL();
}
m_state = ret? UDBS_DB_UNLINK: UDBS_DB_LINK;
}
catch(DCRMDBException& e)
{
m_state = UDBS_DB_UNLINK;
ret = -1;
}
catch(UDBException& e)
{
m_imp->Release();
m_state = UDBS_DB_UNLINK;
ret = -1;
}
return ret;
}
virtual void Commit()
{
try
{
m_imp->Commit();
}
catch(DCRMDBException& e)
{
UDBSTATE st = CheckOraDBConnected(e.GetSqlErrorCode());
if(st != UDBS_NONE)m_state = st;
throw UDBException(e.GetErrorCode(), e.GetErrorInfo(), e.GetSqlErrorCode(), e.GetSqlErrorInfo(), e.GetSqlState());
}
}
virtual void Rollback()
{
try
{
m_imp->Rollback();
}
catch(DCRMDBException& e)
{
UDBSTATE st = CheckOraDBConnected(e.GetSqlErrorCode());
if(st != UDBS_NONE)m_state = st;
throw UDBException(e.GetErrorCode(), e.GetErrorInfo(), e.GetSqlErrorCode(), e.GetSqlErrorInfo(), e.GetSqlState());
}
}
virtual UDBSTATE State(bool force=false)
{
if(m_state!=UDBS_DB_LINK || !force)return m_state;
/* force check the db state */
try
{
if(!m_sql)
{
m_sql = new DCRMDBDQL(m_imp);
m_sql->Prepare("select 1 from dual");
}
m_sql->UnBindParam();
m_sql->Query();
m_state = UDBS_DB_LINK;
}
catch(DCRMDBException& e)
{
UDBSTATE st = CheckOraDBConnected(e.GetSqlErrorCode());
if(st != UDBS_NONE)m_state = st;
delete m_sql;
m_sql = NULL;
}
return m_state;
}
void SetState(UDBSTATE state)
{
m_state = state;
}
virtual const char* GetConStr()
{
return m_scon.c_str();
}
virtual UDBSQL* Stmt(const char* sql);
DCRMDBConnection* GetImpDB(){return m_imp;}
void regSQL(UDBSQL* sql)
{
m_vSQL.insert(sql);
}
void unregSQL(UDBSQL* sql)
{
m_vSQL.erase(sql);
}
void ResetSQL()
{
for(std::set<UDBSQL*>::iterator it = m_vSQL.begin(); it != m_vSQL.end(); it++)
{
(*it)->Reset();
}
}
private:
DCRMDBConnection* m_imp;
DCRMDBDQL* m_sql;
UDBSTATE m_state;
std::string m_scon;
std::set<UDBSQL*> m_vSQL;
};
/*----------------------------------------------------------------------------*/
class UDBRMDBDMLImp: public UDBSQL
{
public:
/* 构造函数 */
UDBRMDBDMLImp(UDBRMDBConnectionImp* pCon)
:m_pCon(pCon)
,m_pDML(NULL)
,m_state(UDBS_NONE)
{
try
{
m_pDML = new DCRMDBDML(pCon->GetImpDB());
}
catch(DCRMDBException& e)
{
UDBSTATE st = CheckOraDBConnected(e.GetSqlErrorCode());
if(st != UDBS_NONE)m_pCon->SetState(st);
throw UDBException(e.GetErrorCode(), e.GetErrorInfo(), e.GetSqlErrorCode(), e.GetSqlErrorInfo(), e.GetSqlState());
}
}
/* 析构函数 */
virtual ~UDBRMDBDMLImp()
{
m_pCon->unregSQL(this);
delete m_pDML;
}
/* 获取SQL状态 */
virtual UDBSTATE State()
{
return m_state;
}
/* 获取SQL类型 */
virtual UDBSTMT StmtType()
{
return UDMLSTMT;
}
/* 获取连接句柄 */
virtual UDBConnection* Connection()
{
return m_pCon;
}
/* 重置SQL:重新prepare, 绑定参数类型 */
virtual void Reset()
{
std::string ssql = m_pDML->GetSqlString();
Prepare(ssql.c_str());
SetBindParam(m_para);
}
void Prepare(const char* sql)
{
try
{
if(m_state)
{
delete m_pDML;
m_pDML = new DCRMDBDML(m_pCon->GetImpDB());
}
m_pDML->Prepare(sql);
m_state = UDBS_STMT_VALID;
}
catch(DCRMDBException& e)
{
UDBSTATE st = CheckOraDBConnected(e.GetSqlErrorCode());
if(st != UDBS_NONE)m_pCon->SetState(st);
m_state = UDBS_STMT_INVALID;
throw UDBException(e.GetErrorCode(), e.GetErrorInfo(), e.GetSqlErrorCode(), e.GetSqlErrorInfo(), e.GetSqlState());
}
}
/* 执行SQL语句:DQL/DML */
virtual void Execute()
{
try
{
m_pDML->Execute();
}
catch(DCRMDBException& e)
{
UDBSTATE st = CheckOraStmtConnected(e.GetSqlErrorCode());
if(st == UDBS_DB_UNLINK)m_pCon->SetState(st);
if(st != UDBS_NONE)m_state = st;
throw UDBException(e.GetErrorCode(), e.GetErrorInfo(), e.GetSqlErrorCode(), e.GetSqlErrorInfo(), e.GetSqlState());
}
}
/* 获取查询下一行数据 */
virtual bool Next()
{
return false;
}
/* 查询结束关闭:M2DB */
virtual void Close()
{
// do nothing
}
/* 获取DML操作影响结果数 */
virtual int GetRowCount()
{
int row = 0;
try
{
m_pDML->GetRowCount(row);
}
catch(DCRMDBException& e)
{
throw UDBException(e.GetErrorCode(), e.GetErrorInfo(), e.GetSqlErrorCode(), e.GetSqlErrorInfo(), e.GetSqlState());
}
return row;
}
/*