⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdbquery.h

📁 Oracle OCI的C++类的一个封装
💻 H
字号:
#ifndef _OCIQuery_h
#define _OCIQuery_h

#include "TException.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <oci.h>
#include <oratypes.h>
#include <ocidfn.h>
#include <ocidem.h>
#include <ociapr.h>
#include <oci.h>

/*备注:所有SIZE宏定义考虑+1*/
#ifndef SIZE_DATE_TIME
#define SIZE_DATE_TIME      15                              //日期时间格式大小YYYYMMDDHHMISS
#endif  //SIZE_DATE_TIME

#ifndef SIZE_DATE_TIME_FULL
#define SIZE_DATE_TIME_FULL             20                  //日期时间格式大小为YYYY?MM?DD HH?MI?SS
#endif

extern int SqlDone();



#ifdef boolean
#undef boolean
#endif


#ifdef WIN32
#pragma warning(disable: 4290)
#pragma warning(disable: 4267)
#endif


#ifdef WIN32

//#ifndef int64
//	#define int64 long long
//#endif

#ifndef llong
#define llong long long
#endif

#else

#ifdef LONG64

#ifndef int64
#define int64  long
#endif

#ifndef llong
#define llong  long
#endif

#else

#ifndef int64
#define int64  long long 
#endif

#ifndef llong
#define llong  long long 
#endif

#endif

#endif


const int PREFETCH_ROWS = 200;						//预先提取n行数据到缓冲区,减少网络流量
const	int MAX_STRING_VALUE_LENGTH = 255;			//返回的字符串最大的列、返回过程参数长度
const	int MAX_LOB_BUFFER_LENGTH = 1024;			//LOB数据缓冲区的最大空间
const	int MAX_ERRMSG_LENGTH = 1024;					//错误信息的最大长度
const	int MAX_SQLSTMT_LENGTH = 1024;				//出现错误的SQL语句长度
const	int MAX_PARAMS_COUNT = 100;						//参数最大数目
const	int MAX_ERR_CAT_LENGTH = 50;					//错误分类长度
const	int LOB_FLUSH_BUFFER_SIZE = 400*1024;		//LOB数据积累到此量时,写入数据库

//error message definination:
const	char* const ERR_GENERAL = "General Error: %s"; //throw TDBException("TDBQuery(TDBDatabase &db)", ERR_GENERAL, "Can not declare a TDBQuery when the database is not connected");
const	char* const ERR_INDEX_OUT_OF_BOUND = "%s";    //throw TDBException(fSqlStmt , ERR_INDEX_OUT_OF_BOUND, "field index out of bound when call Field(i)");	
const	char* const ERR_DB_INIT = "OCI: OCI handles init fail in TDatabase constructor: @line:%d";
const	char* const ERR_SET_LOGIN = "OCI: You can only set login infomation on disconnect status: line %d";
const	char* const ERR_CONNECT_NO_LOGIN_INFO = "No login information provided before Connect(), call SetLogin first, line:%d";
const	char* const ERR_NO_DATASET = "OCI: function:%s , Result Dataset is on Bof/Eof. field:%s"; //throw TDBException(fParentQuery->fSqlStmt, ERR_NO_DATASET, "asBlobBuffer()", name);
const	char* const ERR_DATA_TYPE_CONVERT = "Data type convertion error: field:%s data type:%d can not be access by %s"; //throw TDBException(fParentQuery->fSqlStmt, ERR_DATA_TYPE_CONVERT, name, type, "asLobBuffer()");
const	char* const ERR_NOMORE_MEMORY_BE_ALLOCATED = "no more memory can be allocate when :%s, source code:%d"; //throw TDBException(fParentQuery->fSqlStmt, ERR_NOMORE_MEMORY_BE_ALLOCATED, "asBlobBuffer()", __LINE__);
const	char* const ERR_FILE_IO = "%s: can not open file:%s"; //throw TDBException(fParentQuery->fSqlStmt, ERR_FILE_IO, "LoadFromFile()", fileName);
const	char* const ERR_MEM_BUFFER_IO = "asBlobWriter() error: read from file to buffer, field:%s, file:%s, @line:%d"; //throw TDBException(fParentQuery->fSqlStmt, ERR_MEM_BUFFER_IO, name, fileName, __LINE__);
const	char* const ERR_DATA_TYPE_NOT_SUPPORT = "field:%s, datatype:%d not yet supported"; //, pCurrField->name,innerDataType);
const	char* const ERR_PARAM_NOT_EXISTS = "param:%s does not exists."; //throw TDBException(fSqlStmt, ERR_PARAM_NO_EXISTS, paramName, "check spelling error");
const	char* const ERR_FIELD_NOT_EXISTS = "field:%s does not exists.";
const	char* const ERR_INVALID_METHOD_CALL	= "%s: invalid call method:%s";
const	char* const ERR_CAPABILITY_NOT_YET_SUPPORT = "capability not support yet:%s"; //例如参数个数超越范围
const	char* const ERR_READ_PARAM_DATA = "read parameter value data type error, parameter name:%s, method:%s";

//const define:
const char* const NULL_STRING = "";
const int NULL_NUMBER = 0;

/* classes defined in this file: */
class TDBException;
class TDBDatabase;
class TDBQuery;
class TDBField;
class TDBParam;
class TDBSession;
class TDBDirPath;	//define in TDBDirPath.h

class TDBException : public TException
{
public:
    char *GetErrMsg() const;
    char *GetErrSql() const;

public:
    TDBException(sword errNumb, OCIError *err,const char *cat,const char *sql);//执行OCI函数发生的错误
    TDBException(const char *sql, const char* errFormat, ...);	
    virtual ~TDBException();

private:
    char	errCategory[MAX_ERR_CAT_LENGTH+1];	//错误分类
    text	errMessage[MAX_ERRMSG_LENGTH+1];		//错误信息
    char	errSQL[MAX_SQLSTMT_LENGTH+1];			//发生错误的sql语句
    int	errNo;										//错误号
};

class TDBDatabase
{
    friend class TDBQuery;
    friend class TDBSession;
    friend class TDBDirPath;
public:
		

public:
    TDBDatabase() ;
    virtual ~TDBDatabase();
    void SetLogin(char *user, char *password, char *tnsString) ;
    bool Connect() ;
    bool Connect(char *usr, char *pwd, char *tns) ;
    void Disconnect() ;
	void TransBegin();
    void Commit();
    void Rollback();
    OCISession *hUser;
    //OCISvcCtx *hSvc;						//服务
    OCISvcCtx *hDBSvc;		//用于登录链接服务器	

private:
    char *usr, *pwd, *tns;	//登录名
    bool fConnected;			//在Connect中是否连接成功
    sword fErrorNo;						//错误号
    void CheckError() ;		//用于判断当前的语句是否正确执行,如果有错误则把错误信息放入errMsg;

    OCIError *hDBErr;

    OCIEnv *hEnv;
    OCIServer *hSvr;
};

class TDBParam
{
    friend class TDBQuery;
public:
    virtual ~TDBParam();
    char	*name;

    int     AsInteger() ;	//读取返回参数值
    double  AsFloat() ;
    long    AsLong() ;
    char*   AsString() ;
    bool    isNULL() ;
private:
    TDBParam();
    ub2		dataType;

    int		intValue;
    double	dblValue;			//存储输入和输出的值(缓冲区)
    long		longValue;			//long数据缓冲区
    char		*stringValue;		//字符串返回缓冲区

    int    * intArray;    //INT数组
    double * dblArray;    //DOUBLE数组
    long   * longArray;  //LONG数组
    long long * llongArray;  //LONG LONG数组
    char ** stringArray; //STRING数组
    int   stringSize;    //string数组中的string大小

    bool		fIsOutput;			//是否是输出参数.默认是输入参数
    sb2		indicator;			//在返回值时候是否为空
    OCIBind  *hBind;
};

class TDBField
{
    friend class TDBQuery;

public:	
    virtual ~TDBField(); 
    char	*name;				//字段名称
    long	size;					//数据长度
    long	type;					//数据类型 in(INT_TYPE,FLOAT_TYPE,DATE_TYPE,STRING_TYPE,ROWID_TYPE)
    int	precision;			//数值总长度
    int	scale;				//数值中小数点个数
    bool	nullable;			//字段定义时是否允许为空值--为了和其他的相一致

    bool		isNULL();			//在fetch过程中该列的数据是否为空
    char		*AsString() ;
    double	AsFloat() ;
    llong	AsInteger() ;

    //Blob处理
    void		AsBlobFile(const char *fileName) ;			//读取到file中
    void		LoadFromFile(const char *fileName) ;			//写入到blob中
    void		LoadFromBuffer(unsigned char *buf, unsigned int bufLength) ;	//把LOB的内容用缓冲区内容替代
    void		AsBlobBuffer(unsigned char* &buf, unsigned int *bufLength) ;	//保存到缓冲区,缓冲区的大小自动创建,并返回缓冲区大小*bufLength.

    //日期处理
    char		*AsDateTimeString() ;	//把日期型的列以HH:MM:DD HH24:MI格式读取,使用asString()读取的日期型数据类型为HH:MM:DD
    void		AsDateTime(int &year, int &month, int &day, int &hour, int &minute, int &second) ; //返回日期的各个部分
private:
    //日期处理
    void		AsDateTimeInternal(int &year, int &month, int &day, int &hour, int &minute, int &second) ; //返回日期的各个部分,没有作其他校验,只是内部调用					
    TDBQuery *fParentQuery;					//指向该Field所属于的Query
    TDBField();
    //数据缓冲区,分别为字符串、整数、浮点数分配空间
    ub1	fStrBuffer[MAX_STRING_VALUE_LENGTH];	//用于保存转换为字符串后的值
    ub1	*fDataBuf;						//在分析字段时候获得空间max(该列的最大长度,MAX_STRING_VALUE_LENGTH), 在Destructor中释放
    OCILobLocator *hBlob;				//支持LOB
    sb2	*fDataIndicator;				//在defineByPos中使用,用于在fetch时察看是否有字段值返回、字段值是否被截断;valueIsNULL, isTruncated根据此值获得结果

    ub2   fReturnDataLen;				//读取数据时返回的真实长度
    ub2	fInternalType;					//Oracle内部数据类型
    ub2	fRequestType;					//在读取数据时候的请求数据类型
    OCIDefine *hDefine;					//用于读取列信息
};

class TDBQuery
{
    friend class TDBField;

public:
    //主要功能
    void Close();													//关闭SQL语句,以准备接收下一个sql语句
    void SetSQL(const char *inSqlstmt) ;								//设置Sqlstatement
    void Open(int prefetchRows=PREFETCH_ROWS) ;			//打开SQL SELECT语句返回结果集
    bool Next() ;													//移动到下一个记录
    bool Execute(int iters=1) ;	                          //执行非SELECT语句,没有返回结果集
	bool TransBegin();									//事务开启
    bool Commit();													//事务提交
    bool Rollback();												//事务回滚
    int  RowsAffected() { return fTotalRowsFetched;};	//DELETE/UPDATE/INSERT语句修改的记录数目
    int  GetSQLCode() { return fErrorNo;};				//返回Oracle执行结果代码

    //与列信息相关				
    int FieldCount() ;												//总共有几个列
    TDBField& Field(int index)		;						//返回第i个列信息
    TDBField& Field(const char *fieldName) ;						//根据列名(不分大小写)返回列信息; 建议使用Field(int i)获得更高的效率

    //与参数信息相关
    int ParamCount() ;
    TDBParam& Param(int index) ;								//返回第i个列信息
    TDBParam& Param(const char *paramName) ;						//根据列名(不分大小写)返回列信息; 建议使用Field(int i)获得更高的效率
    //以下是设置参数值
    void SetParameter(const char *paramName, const char* paramValue) ; 	
    void SetParameter(const char *paramName, const char paramValue) ; 	//add by fu.wenjun@20041125

	void SetParameter(const char *paramName, int paramValue);
    void SetParameter(const char *paramName, double paramValue);
    void SetParameter(const char *paramName, long paramValue);
    void SetParameter(const char *paramName, long long paramValue) ;
    void SetParameterNULL(const char *paramName) ;

    /*备注:增加int iArraySize=0为了兼容Informix部分的同名函数,OCI部分不进行任何处理*/
    //数组操作
    void SetParamArray(const char *paramName, char     ** paramValue, int iStructSize, int iStrSize ,int iArraySize=0,bool isOutput = false) ; 	
    void SetParamArray(const char *paramName, int       * paramValue, int iStructSize,               int iArraySize=0,bool isOutput = false) ; 
    void SetParamArray(const char *paramName, double    * paramValue, int iStructSize,               int iArraySize=0,bool isOutput = false) ;
    void SetParamArray(const char *paramName, long      * paramValue, int iStructSize,               int iArraySize=0,bool isOutput = false) ;
    void SetParamArray(const char *paramName, long long * paramValue, int iStructSize,               int iArraySize=0,bool isOutput = false) ;
    //constructor & destructor
    TDBQuery(TDBDatabase *oradb) ;
    TDBQuery(TDBDatabase *oradb,TDBSession *session) ;
    virtual ~TDBQuery();

private:
    char *fSqlStmt;						    //保存open的Select语句,可以方便调试
    ub2 fStmtType;							//***ub2!!! 保存sqlstmt的类型:SELECT/UPDATE/DELETE/INSERT/CREATE/BEGIN/ALTER...
    bool fActivated;						//是否已经处于打开状态,在调用OCIStmtPrepare成功后为True

    unsigned	fFetched;					//0..prefetchRows
    unsigned	fPrefetchRows;				//1.. 
    unsigned	fCurrRow;					//0..fetched */
    unsigned	fTotalRowsFetched;		    //rows fetched from the start

    int fFieldCount;						//字段个数
    TDBDatabase *db;						//此query属于哪个Dabase,在Constructor中创建
    TDBField *fieldList;				    //在内部保存的所有字段信息
    void GetFieldsDef() ;					//获得字段信息,并为字段分配取值的缓冲区

    TDBParam *ParamByName(const char *paramName) ;//在内部使用,直接返回参数的指针

    void CheckError() ;					//用于判断当前的语句是否正确执行,如果有错误则把错误信息放入errMsg;

    int fParamCount;						//参数个数
    TDBParam *paramList;				//所有参数设置的信息
    void GetParamsDef() ;					//在setSQL时候获得参数信息
    int nTransTimes;						//是否曾经执行过Execute()事务操作,以便与回滚.

    //OCITrans* hTrans;
    OCIStmt *hStmt;						//用于分析sql语句的handle
    OCIError *hErr;						//错误处理
    sword fErrorNo;						//错误号
    bool fEof;								//在Fetch时候,已经达到最后一个记录,防止已经读到最后一个记录后,又fetch发生的错误
    bool fBof;								//在Open()时候为True,在Next()如果有数据为false;用于判断用户是否可以从缓冲区中读取列值,该部分尚未完成
    bool fOpened;							//数据集是否打开	
#ifdef __DEBUG__
    bool bExecuteFlag;
#endif
};

class TDBSession
{	
public:
    TDBSession(TDBDatabase *pDB);
    virtual ~TDBSession();

    void sessionBegin();
    void sessionEnd();

private:

    OCISvcCtx	*m_hSrvCtx;
    OCISession	*m_hSession;
    OCIError	*m_hError;

    bool	m_bActive;

    int	m_iErrorNo;

    void CheckError();

    friend	class TDBDirPath;
    friend  class TDBQuery;	
};

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -