/********************************************
[Home]
[oci_tl Home]
[Back]
********************************************/
/* Copyright (c) Vasiliy Astapov 2000. All Rights Reserved. */
#ifndef __oci_tl__
#define __oci_tl__
#include <oci.h>
#include <string>
#include <algorithm>
#include <exception>
#include <cassert>
#include <iostream>
using namespace std;
namespace ina_lib
{
//begin namespace
using namespace std;
typedef unsigned char uchar;
#define P_ENV poci_env->p_env
#define P_ERR db->p_err
#define P_SVC db->p_svc
#define CHECKERROR() db->checkerror(rc)
/////////////////////////////////////////////////
// oci_tl_exception
/////////////////////////////////////////////////
class oci_tl_exception : public exception
{
public:
oci_tl_exception() throw()
{
error_msg="Error - Another error";
}
oci_tl_exception(const char* str) throw()
{
error_msg=string("Error - ")+str;
}
const char* what() const throw()
{
return error_msg.c_str();
}
private:
string error_msg;
};
/////////////////////////////////////////////////
// oci_var
/////////////////////////////////////////////////
class oci_var_base
{
//friend class oci_cursor;
public:
operator OCIBind**()
{
return &p_bnd;
}
operator OCIDefine**()
{
return &p_dfn;
}
const string name()
{
return s_name;
}
void* ptr()
{
return v;
}
int type()
{
return i_type;
}
int size()
{
return sz;
}
explicit oci_var_base(const char* nm) throw()
{
init();
if(nm)
s_name=nm;
else
s_name="";
}
bool is_null()
{
if(ind==-1)
return true;
return false;
}
sb2* get_indicator()
{
return &ind;
}
void* get_val()
{
if(is_null())
*v=0;
return v;
}
// Operators
protected:
sb2 ind;
OCIBind *p_bnd;
OCIDefine *p_dfn;
string s_name;
int i_type;
char *v;
int sz;
void init()
{
p_bnd=0;
p_dfn=0;
v=0;
i_type=0;
ind=0;
}
private:
//No access from basic_stream <<
operator void*();
};
template<int _sz> class oci_var : public oci_var_base
{
public:
explicit oci_var(const char* nm):oci_var_base(nm)
{
init();
}
~oci_var()
{
delete [] v;
}
protected:
void init()
{
oci_var_base::init();
sz=_sz;
v=new char[_sz];
*v=0;
}
//currently not supported
oci_var& operator=(oci_var&);
oci_var(oci_var&);
};
/////////////////////////////////////////////////
// oci_var_string
/////////////////////////////////////////////////
template <int _sz=128>
class oci_var_string : public oci_var<_sz>
{
public:
explicit oci_var_string<_sz>(const char* nm=0):oci_var<_sz>(nm)
{
i_type=SQLT_STR;
}
const char* c_str()
{
return (const char*)get_val();
}
operator const char*()
{
return c_str();
}
oci_var_base& operator=(const char* str)
{
memset(v,0,sz);
int n=sz-1<strlen(str)?sz-1:strlen(str);
strncpy(v,str,n);
return *this;
}
oci_var_base& operator=(int val)
{
sprintf(v,"%d",val);
return *this;
}
};
class oci_var_int : public oci_var<4>
{
public:
explicit oci_var_int(const char* nm=0):oci_var<4>(nm)
{
i_type=SQLT_INT;
}
const int i_val()
{
return *(int*)get_val();
}
operator const int()
{
return i_val();
}
oci_var_base& operator=(int n)
{
*(int*)v=n;
return *this;
}
};
/////////////////////////////////////////////////
// oci_db
/////////////////////////////////////////////////
class oci_env
{
public:
operator OCIEnv*()
{
assert(p_env);
return p_env;
}
oci_env() :created(false)
{
p_env=0;
create();
}
~oci_env()
{
destroy();
}
protected:
OCIEnv *p_env;
bool created;
private:
void create()
{
if(created)
return;
int rc;
/* Initialize OCI */
rc = OCIInitialize((ub4) OCI_THREADED|OCI_OBJECT, (dvoid *)0,
(dvoid * (*)(dvoid *, size_t)) 0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *)) 0 );
/* Initialize evironment */
rc = OCIEnvInit( (OCIEnv **) &p_env, OCI_DEFAULT /*| OCI_NO_MUTEX*/ , (size_t) 0, (dvoid **) 0 );
if(rc)
throw oci_tl_exception("Can't initialize environment");
created=true;
}
void destroy()
{
if(created)
OCIHandleFree((dvoid *) p_env, OCI_HTYPE_ENV);
created=false;
}
};
class oci_db
{
public:
operator OCIError* ()
{
assert(p_err);
return p_err;
}
operator OCISvcCtx* ()
{
assert(p_svc);
return p_svc;
}
operator OCIEnv*()
{
assert(poci_env);
return (OCIEnv*)*poci_env;
}
oci_db() throw()
{
logged_in=false;
b_env_holder=false;
poci_env=0;
p_err=0;
p_svc=0;
}
oci_db(oci_env &env) throw()
{
logged_in=false;
b_env_holder=false;
poci_env=&env;
}
oci_db(const char* username,const char* password, const char* service,oci_env* env=0)
{
logged_in=false;
if(!env)
{
create_env();
init_by_env(*poci_env);
}
else
init_by_env(*env);
login(username,password,service);
}
~oci_db()
{
cerr<<"In destructor"<<endl;
logout();
if(b_env_holder)
delete_env();
}
void init_by_env(oci_env &env)
{
poci_env=&env;
}
void login(const char* username,const char* password, const char* service)
{
_username=username;
_password=password;
_service=service;
if(logged_in)
logout();
if(!poci_env)
create_env();
int rc=0;
/* Initialize handles */
rc = OCIHandleAlloc( (dvoid *) static_cast<OCIEnv*>(*this), (dvoid **) &p_err, OCI_HTYPE_ERROR,
(size_t) 0, (dvoid **) 0);
if(rc!=0)
throw oci_tl_exception("Can't allocate error buffer");
rc = OCIHandleAlloc( (dvoid *) static_cast<OCIEnv*>(*this), (dvoid **) &p_svc, OCI_HTYPE_SVCCTX,
(size_t) 0, (dvoid **) 0);
if(rc!=0)
throw oci_tl_exception("Can't allocate service handle");
rc = OCILogon(static_cast<OCIEnv*>(*this), p_err, &p_svc,
(uchar*)username, strlen(username),
(uchar*)password, strlen(password),
(uchar*)service, strlen(service));
checkerror(rc);
logged_in=true;
}
void logout()
{
if(!logged_in)
return;
OCILogoff(p_svc, p_err);
OCIHandleFree(p_svc,OCI_HTYPE_SVCCTX);
OCIHandleFree(p_err,OCI_HTYPE_ERROR);
//p_svc=0;
//p_err=0;
logged_in=false;
}
void checkerror(int rc)
{
if (rc != 0)
{
*errbuf=0;
OCIErrorGet((dvoid *)p_err, (ub4) 1, (text *) NULL, &errcode, (uchar*)errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
// if(check_null(errbuf))
// return;
throw oci_tl_exception(errbuf);
}
}
protected:
void _assert_()
{
assert(poci_env);
assert(p_err);
assert(p_svc);
}
void create_env()
{
if(b_env_holder)
delete_env();
poci_env=new oci_env;
b_env_holder=true;
}
void delete_env()
{
if(poci_env)
delete poci_env;
poci_env=0;
b_env_holder=false;
}
/*
bool check_null(const char* errmsg)
{
string err=errmsg;
if(err.find("ORA-01405")!=string::npos)
return true;
return false;
}
*/
oci_env* poci_env;
OCIError *p_err;
OCISvcCtx *p_svc;
char errbuf[2048];
int errcode;
bool b_env_holder;
bool logged_in;
string _username;
string _password;
string _service;
};
//////////////////////////////////////////////////////////////////
// oci_cursor
//////////////////////////////////////////////////////////////////
class oci_cursor
{
public:
bool eof()
{
return _eof;
}
explicit oci_cursor(oci_db &rdb)
{
open();
db=&rdb;
}
explicit oci_cursor(oci_db &rdb,const char* nm)
{
open();
name=nm;
db=&rdb;
}
~oci_cursor()
{
close();
}
void close()
{
int rc;
if(p_sql)
rc = OCIHandleFree((dvoid *) p_sql, OCI_HTYPE_STMT);
p_sql=0;
}
void open()
{
fetch_count=1;
executed=false;
cur_bind_pos_out=0;
cur_bind_pos_in=0;
_eof=false;
parsed=false;
p_bnd=0;
p_sql=0;
}
void bind(int pos, oci_var_base &var)
{
assert(&var);
if(!parsed)
throw oci_tl_exception("Statment not parsed");
int rc;
rc = OCIBindByPos(p_sql, static_cast<OCIBind**>(var), static_cast<OCIError*>(*db)/*P_ERR*/, pos,
(dvoid *) var.ptr(), var.size(), var.type(), /*(dvoid *) 0*/ var.get_indicator(),
(ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT);
CHECKERROR();
}
void bind(const char* name, oci_var_base &var)
{
assert(&var);
if(!parsed)
throw oci_tl_exception("Statment not parsed");
int rc;
rc = OCIBindByName(p_sql, static_cast<OCIBind**>(var), static_cast<OCIError*>(*db)/*P_ERR*/, (text *) name,
-1, (dvoid *) var.ptr(), var.size(), var.type(), /*(dvoid *) 0*/ var.get_indicator(),
(ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT);
CHECKERROR();
}
void bind(oci_var_base &var)
{
assert(&var);
if(var.name().size())
bind(var.name().c_str(),var);
else
{
//throw oci_tl_exception("OCI_TL : variable haven't name");
bind(++cur_bind_pos_in,var);
}
}
void bind_out(int pos, oci_var_base &var)
{
assert(&var);
//if(!executed)
//throw oci_tl_exception("Can't bind - wasn't executed");
int rc;
/* Define the select list items */
rc = OCIDefineByPos(p_sql, static_cast<OCIDefine**>(var), static_cast<OCIError*>(*db)/*P_ERR*/, pos,
(dvoid *) var.ptr(), var.size(), var.type(), /*(dvoid *) 0*/ var.get_indicator(),
(ub2 *)0,(ub2 *)0, OCI_DEFAULT);
CHECKERROR();
}
void bind_out(oci_var_base &var)
{
bind_out(++cur_bind_pos_out,var);
}
/*
void bind_out(const char* name,oci_cursor& var)
{
bind(name,var);
}
*/
void bind(const char* name,oci_cursor& var)
{
assert(&var);
if(!parsed)
throw oci_tl_exception("Statment not parsed");
int rc;
rc = OCIHandleAlloc( (dvoid *) static_cast<OCIEnv*>(*db), (dvoid **) &var.p_sql, OCI_HTYPE_STMT ,
(size_t) 0, (dvoid **) 0);
CHECKERROR();
int type=SQLT_RSET;
rc = OCIBindByName (p_sql, &var.p_bnd, static_cast<OCIError*>(*db)/*P_ERR*/,
(text *)name, (sb4)strlen((char *)name),
(dvoid *)&var.p_sql, (sb4) 0, SQLT_RSET, (dvoid *)0,
(ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, (ub4)OCI_DEFAULT);
CHECKERROR();
}
void bind(oci_cursor &var)
{
assert(&var);
if(var.name.size())
bind(var.name.c_str(),var);
else
throw oci_tl_exception("OCI_TL : cursor haven't name");
}
void execute()
{
_assert_();
if(!parsed)
throw oci_tl_exception("Statment not parsed");
int rc;
/* Execute the SQL statment */
rc = OCIStmtExecute(static_cast<OCISvcCtx*>(*db), p_sql, static_cast<OCIError*>(*db)/*P_ERR*/, (ub4) fetch_count, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT);
if(rc==100)
{
executed=true;
_eof=true;
return;
}
CHECKERROR();
executed=true;
_eof=false;
}
bool fetch()
{
_assert_();
int rc;
rc = OCIStmtFetch(p_sql, static_cast<OCIError*>(*db)/*P_ERR*/, 1, 0, 0);
if(rc == OCI_NO_DATA)
_eof=true;
else if(rc!=0)
{
CHECKERROR();
}
else
_eof=false;
return !eof();
}
void parse(const char* stmt)
{
_assert_();
int rc;
string s=stmt;
transform(s.begin(),s.end(),s.begin(),toupper);
if(s.find("SELECT")!=string::npos)
fetch_count=0;
/* Allocate and prepare SQL statement */
rc = OCIHandleAlloc( (dvoid *) static_cast<OCIEnv*>(*db), (dvoid **) &p_sql,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0);
CHECKERROR();
rc = OCIStmtPrepare(p_sql, static_cast<OCIError*>(*db)/*P_ERR*/, (uchar*)stmt,
(ub4) strlen(stmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
CHECKERROR();
parsed=true;
}
protected:
bool parsed;
bool _eof;
int fetch_count;
string name;
OCIBind *p_bnd;
OCIStmt *p_sql;
oci_db *db;
bool executed;
int cur_bind_pos_out;
int cur_bind_pos_in;
void _assert_()
{
assert(db);
}
};
//////////////////////////////////////////////////////////////////
// oci_stream
//////////////////////////////////////////////////////////////////
class oci_stream : public oci_cursor
{
public:
explicit oci_stream(oci_db &rdb):oci_cursor(rdb){};
explicit oci_stream(oci_db &rdb,const char* name) : oci_cursor(rdb,name){};
oci_stream& begin()
{
return *this;
}
bool end()
{
return eof();
}
oci_stream& parse(const char* stmt)
{
oci_cursor::parse(stmt);
return *this;
}
//operators
oci_stream& operator<<(oci_var_base& var)
{
bind(var);
return *this;
}
oci_stream& operator<<(oci_cursor& var)
{
bind(var);
return *this;
}
oci_stream& operator<<(oci_stream& (*f)(oci_stream& str))
{
f(*this);
return *this;
}
oci_stream& operator>>(oci_var_base& var)
{
bind_out(var);
return *this;
}
//Iterator class
class iterator
{
oci_stream* str;
public:
iterator():str(0){}
iterator(oci_stream& s):str(&s){};
private:
// not implemented yet
oci_stream& operator++();
bool operator !=(oci_stream& s);
};
};
// global functions
oci_stream& _parse(oci_stream& s,const char* stmt);
struct smanip
{
oci_stream& (*f)(oci_stream&,const char*);
string str;
smanip(oci_stream& (*ff)(oci_stream&,const char* ),const char* s):f(ff),str(s){};
};
inline smanip parse(const char* stmt)
{
return smanip(_parse,stmt);
}
inline oci_stream& operator<<(oci_stream& str,smanip& m)
{
return m.f(str,m.str.c_str());
}
inline oci_stream& _parse(oci_stream& s,const char* stmt)
{
return s.parse(stmt);
}
inline oci_stream& execute(oci_stream& str)
{
str.execute();
return str;
}
// end ina_lib namespace
};
//
#endif //__oci_tl__
/**************************************************
[Home]
[oci_tl Home ]
[Back] [Top]
**************************************************/