#ifndef _DB_H #define _DB_H #include #ifdef _WIN32 # include # pragma comment(lib, "odbc32.lib") # pragma comment(lib, "odbccp32.lib") #endif #include #include namespace ODBCSQL { static inline bool check(RETCODE rc) { return (rc==SQL_SUCCESS)||(rc==SQL_SUCCESS_WITH_INFO)||(rc==SQL_NO_DATA); } } //using namespace std; class DBRow{ HSTMT hstmt; int count; public: DBRow(HSTMT st){hstmt=st;count=1;} bool getData(std::string &s){ if (!count) {s.clear();return false;} char dummy[256]; char *str=dummy; SQLINTEGER rbufsize = 0; RETCODE rc; rc = SQLGetData( hstmt, count, SQL_C_CHAR, str, (SQLINTEGER)sizeof(dummy), &rbufsize); if (rc==1) { str = new char[rbufsize+1]; rc = SQLGetData( hstmt, count, SQL_C_CHAR, str, (SQLINTEGER)(rbufsize+1), &rbufsize); s=str; delete [] str; } else { s=str; } count++; return ODBCSQL::check(rc); } bool getInt(int type,void *p,int size){ if (!count) return false; SQLINTEGER rbufsize = 0; RETCODE rc; rc = SQLGetData(hstmt , count, type, p, (SQLINTEGER)size, &rbufsize); count++; if (rc<0) return false; return ODBCSQL::check(rc); } bool getData(long &s){ return getInt(SQL_C_SLONG,&s,sizeof(s)); } bool getData(int &s){ return getInt(SQL_C_SLONG,&s,sizeof(s)); } bool getData(unsigned long &s){ return getInt(SQL_C_ULONG,&s,sizeof(s)); } bool getData(unsigned int &s){ return getInt(SQL_C_ULONG,&s,sizeof(s)); } bool getData(const void *v){ if (!v) {count++;return true;} return false; } template bool get(T &d,int n){ count=n; return getData(d); } template DBRow& operator >> (T &dst) { count=1; getData(dst); return *this; } DBRow& operator >> (const void* v) { count=1; getData(v); return *this; } template DBRow& operator , (T &dst) { getData(dst); return *this; } DBRow& operator , (const void* v) { getData(v); return *this; } operator HSTMT(){return hstmt;} }; class DBParam { HSTMT hstmt; RETCODE rc; int count; public: DBParam(HSTMT st){hstmt=st;count=1;} bool bind( int type, int ptype, const void *param, int ColumnSize = 0, int DecimalDigits = 0) { rc = SQLBindParameter(hstmt, count, SQL_PARAM_INPUT, type, ptype, ColumnSize, DecimalDigits, (SQLPOINTER)param, 0, 0); count++; return true; } bool bind(const std::string &d){ return bind(SQL_C_CHAR,SQL_VARCHAR,d.c_str()); } bool bind(const char *d) { return bind(SQL_C_CHAR,SQL_VARCHAR,d); } bool bind(const long &d) { return bind(SQL_C_SLONG,SQL_INTEGER,&d); } bool bind(const int &d) { return bind(SQL_C_SLONG,SQL_INTEGER,&d); } bool bind(const unsigned long &d) { return bind(SQL_C_ULONG,SQL_INTEGER,&d); } bool bind(const unsigned int &d) { return bind(SQL_C_ULONG,SQL_INTEGER,&d); } template DBParam& operator << (const T &d) { bind(d); return *this; } template DBParam& operator , (const T &d) { bind(d); return *this; } }; class DBStmt{ bool m_error; public: HSTMT hstmt; // DBStmt( DBStmt &sth){ // hstmt = sth.hstmt; // m_error = sth.m_error; // sth.hstmt=NULL; // } DBStmt(HDBC hdb){ RETCODE rc; rc = SQLAllocStmt(hdb,&hstmt); m_error=!ODBCSQL::check(rc); } ~DBStmt(){ // finish(); } bool prepare(const std::string &sql) { RETCODE rc; rc = SQLPrepare(hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS); return ODBCSQL::check(rc); } bool execute() { RETCODE rc; rc = SQLExecute(hstmt); m_error = !ODBCSQL::check(rc); return !m_error; } DBRow fetch_row(){ RETCODE rc; rc=SQLFetch(hstmt); m_error=(rc!=SQL_SUCCESS)&&(rc!=SQL_SUCCESS_WITH_INFO); return DBRow(m_error?NULL:hstmt); } DBParam param(){ return DBParam(hstmt); } void finish(){ if ( hstmt ) { SQLFreeStmt(hstmt,SQL_DROP); hstmt = 0; } } void free(){ delete this; } bool error(){return m_error;} template DBParam operator << (const T &d) { return DBParam(hstmt) << d; } template DBRow operator >> (T &d) { return fetch_row() >> d; } DBRow operator >> (const void *d) { return fetch_row() >> d; } DBStmt* operator -> () { return this; } operator void*(){return m_error?NULL:hstmt;} }; typedef DBStmt STH; class DB{ bool m_error; public: HENV henv; HDBC hdbc; DB(const std::string &s,bool autocommit=true){ henv = NULL; hdbc = NULL; connect(s,autocommit); } DB(){ henv = NULL; hdbc = NULL; } ~DB(){close();} bool connect(const std::string &s,bool autocommit=true){ close(); SQLAllocEnv(&henv); SQLAllocConnect(henv,&hdbc); RETCODE rc; rc = SQLDriverConnect(hdbc, 0, (SQLCHAR*)s.c_str(), SQL_NTS, 0, 0, 0,0); if (!autocommit) SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF ); if (!ODBCSQL::check(rc)) close(); m_error = !ODBCSQL::check(rc); return !m_error; } void close() { if (hdbc) { SQLDisconnect(hdbc); SQLFreeConnect(hdbc); hdbc = NULL; } if (henv) { SQLFreeEnv(henv); henv = NULL; } } bool commit(){ RETCODE rc; rc = SQLTransact(henv,hdbc,SQL_COMMIT); m_error = (rc!=SQL_SUCCESS); return !m_error; } bool rollback(){ RETCODE rc; rc = SQLTransact(henv,hdbc,SQL_ROLLBACK); m_error = (rc!=SQL_SUCCESS); return !m_error; } DBStmt prepare(const std::string &sql) { if (hdbc==NULL) return DBStmt(NULL); DBStmt sth(hdbc); sth.prepare(sql); return sth; } bool sql(const std::string &sql) { if (hdbc==NULL) return false; DBStmt sth(hdbc); sth.prepare(sql); bool ret=sth.execute(); m_error = !ret; return ret; } std::string errorstr(){ std::string s; SQLSMALLINT len; char err[256]; char state[256]; //SQLGetDiagRec(SQL_HANDLE_STMT, hdbc, rc, state, err,sizeof(err),&len); //s=err; return s; } bool error(){return m_error;} }; #endif