本代码可以任意转载使用,但请保留出处
//blog.csdn.net/bat603
//by ben
//
//.h
/*
AUTHOR: lizp
MSN:lizp.net@gmail.com
URL:blog.csdn.net/bat603
Description:使用UNIXODBC主页中教程的使用方法,对UnixODBC进行了封装,并增加了锁功能,使用起来非常方便
*/
#ifndef _CPP_ODBC_H_
#define _CPP_ODBC_H_
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
//查询的最大字段数量
#define FIELD_NUM 1024
class CppODBC
{
public:
CppODBC( );
virtual ~CppODBC( );
//公共接口
public:
bool Open( );
bool Close( );
bool Connect( const char* pszDSN, const char* pszUName, const char* pszUPasswd );
bool DisConnect( );
bool Clear( );
unsigned int SQLQuery( const char* pszSQL );
unsigned int SQLExec( const char* pszSQL );
unsigned int SQLExecAutoID( char *pszSQL );
bool IsOpen( );
//查询的结果数量,更新时返回更新的记录数量,删除时返回删除的数量
unsigned int GetCount( );
//返回查询结果的列数两
unsigned int GetColumns( );
int GetIntValue( unsigned int uiIndex );
char * GetStrValue( unsigned int uiIndex );
//取消操作
bool Cancel( );
//获取错误代码
unsigned int GetError( );
//下一个
bool Next( );
bool Eof( );
void Lock();
void UnLock();
private:
SQLHENV V_OD_Env_; // Handle ODBC environment 存放环境变量
SQLHDBC V_OD_hdbc_; // Handle connection 连接句柄
SQLHSTMT V_OD_hstmt_; // SQL语句的句柄
SQLINTEGER V_OD_rowanz_; // 操作影响的记录数量
SQLSMALLINT V_OD_colanz_; // 操作影响的记录包含的字段数量
char* pszField_[FIELD_NUM]; // 存放一条查询结果集,缓冲区根据查询结果创建
int nMaxFiledLen_; //字段的最大值
bool bOpened_;
bool bConnected_;
bool bEof_;
pthread_mutex_t mutex_;
bool mutex_inited_;
};
#endif
//.cpp
/**********************************************
g++ CppODBC.cpp -lodbc -g -o CppODBC
//blog.csdn.net/bat603
//by ben
**********************************************/
#include "CppODBC.h"
#include <string.h>
CppODBC::CppODBC( )
{
bOpened_ = false;
bConnected_ = false;
nMaxFiledLen_ = 512;
bEof_ = false;
for(int i=0; i<FIELD_NUM; i++)
pszField_[i] = NULL;
mutex_inited_ = false;
}
CppODBC::~CppODBC( )
{
if (mutex_inited_)
pthread_mutex_destroy(&mutex_);
Clear( );
}
bool CppODBC::Open( )
{
if ( bOpened_ )//已经打开了
return true;
long V_OD_erg; // result of functions 存放错误代码
// allocate Environment handle and register version
V_OD_erg = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &V_OD_Env_ );
if ( (V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO) )
{
printf("Error AllocHandle/n");
return false;
}
V_OD_erg = SQLSetEnvAttr( V_OD_Env_, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0 );
if ( (V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO) )
{
printf("Error SetEnv/n");
SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env_);
return false;
}
//初始化互斥体
if ( !mutex_inited_ )
{
pthread_mutex_init(&mutex_, NULL);
mutex_inited_ = true;
}
bOpened_ = true;
return true;
}
bool CppODBC::Close( )
{
if ( bConnected_ )
return false;
SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env_);
bOpened_ = false;
return true;
}
bool CppODBC::Connect( const char* pszDSN, const char* pszUName, const char* pszUPasswd )
{
if ( !bOpened_ )
return false;
if ( pszDSN == NULL )
return false;
long V_OD_erg = 0;
SQLCHAR V_OD_stat[64]= {0}; // Status SQL 执行sql语句的结果状态
SQLINTEGER V_OD_err = 0; // sql语句执行后的错误代码
SQLSMALLINT V_OD_mlen = 0; // 错误返回的消息文本大小
SQLCHAR V_OD_msg[256] = {0};// 错误消息缓冲区
// allocate connection handle, set timeout
V_OD_erg = SQLAllocHandle( SQL_HANDLE_DBC, V_OD_Env_, &V_OD_hdbc_ );
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
printf("Error AllocHDB %d/n",V_OD_erg);
return false;
}
//(SQLPOINTER *)
V_OD_erg = SQLSetConnectAttr(V_OD_hdbc_, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
printf("Error SQLSetConnectAttr %d/n",V_OD_erg);
SQLFreeHandle( SQL_HANDLE_DBC, V_OD_hdbc_ );
return false;
}
// Connect to the datasource
//MysqlODBC //MyPostgres // mysqlitedb
V_OD_erg = SQLConnect(V_OD_hdbc_, (SQLCHAR*) pszDSN, SQL_NTS,
(SQLCHAR*) pszUName, SQL_NTS,
(SQLCHAR*) pszUPasswd, SQL_NTS);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
printf("Error SQLConnect %d/n",V_OD_erg);
SQLGetDiagRec( SQL_HANDLE_DBC, V_OD_hdbc_, 1,
V_OD_stat, &V_OD_err, V_OD_msg, 256, &V_OD_mlen );
printf("%s (%d)/n",V_OD_msg, V_OD_err);
SQLFreeHandle( SQL_HANDLE_DBC, V_OD_hdbc_ );
return false;
}
printf("Connected !/n");
V_OD_erg = SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc_ , &V_OD_hstmt_);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
printf("Fehler im AllocStatement %d/n",V_OD_erg);
SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc_, 1, V_OD_stat, &V_OD_err, V_OD_msg, 256, &V_OD_mlen);
printf("%s (%d)/n", V_OD_msg, V_OD_err);
SQLDisconnect( V_OD_hdbc_ );
SQLFreeHandle( SQL_HANDLE_DBC, V_OD_hdbc_ );
return false;
}
bConnected_ = true;
return true;
}
bool CppODBC::DisConnect( )
{
if ( bConnected_ )
{
SQLFreeHandle( SQL_HANDLE_STMT,V_OD_hstmt_ );
SQLDisconnect( V_OD_hdbc_ );
SQLFreeHandle( SQL_HANDLE_DBC, V_OD_hdbc_ );
bConnected_ = false;
}
return true;
}
unsigned int CppODBC::SQLQuery( const char* pszSQL )
{
if ( pszSQL == NULL )
return 0;
long V_OD_erg = 0;
SQLCHAR V_OD_stat[64]= {0}; // Status SQL 执行sql语句的结果状态
SQLINTEGER V_OD_err = 0; // sql语句执行后的错误代码
SQLSMALLINT V_OD_mlen = 0; // 错误返回的消息文本大小
SQLCHAR V_OD_msg[256] = {0};// 错误消息缓冲区
char* pszBuf = NULL;
//清空缓冲区
Clear();
//查询
V_OD_erg=SQLExecDirect(V_OD_hstmt_, (SQLCHAR*)pszSQL, SQL_NTS);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
printf("Error in Select %d/n", V_OD_erg);
SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc_, 1, V_OD_stat, &V_OD_err, V_OD_msg, 256, &V_OD_mlen);
printf("%s (%d)/n",V_OD_msg, V_OD_err);
return 0;
}
//获取查询结果的数量
V_OD_erg = SQLRowCount(V_OD_hstmt_, &V_OD_rowanz_);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
return 0;
}
if ( V_OD_rowanz_ == 0 )//没有查询结果
return 0;
//获取结果字段的数量
V_OD_erg=SQLNumResultCols(V_OD_hstmt_, &V_OD_colanz_);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
return 0;
}
printf("Number of Columns %d/n",V_OD_colanz_);
//绑定字段缓冲区
for ( int i=0; i<V_OD_colanz_; i++ )
{
pszBuf = new char[ nMaxFiledLen_+ 1 ];
memset( pszBuf, 0, nMaxFiledLen_ );
pszField_[ i ] = pszBuf;
SQLBindCol(V_OD_hstmt_, i+1, SQL_C_CHAR, pszBuf, nMaxFiledLen_, &V_OD_err);
}
//得到一行结果,结果放在绑定的缓冲区里面
V_OD_erg = SQLFetch( V_OD_hstmt_ );
if ( V_OD_erg != SQL_NO_DATA )
bEof_ = false;
return V_OD_rowanz_;
}
bool CppODBC::Clear( )
{
V_OD_rowanz_ = 0;
V_OD_colanz_ = 0;
bEof_ = true;
for (int i=0; i<FIELD_NUM; i++)
{
if ( pszField_[i] != NULL )
delete [] pszField_[i];
pszField_[i] = NULL;
}
return true;
}
unsigned int CppODBC::SQLExec( const char* pszSQL )
{
if ( pszSQL == NULL )
return 0;
long V_OD_erg = 0;
SQLCHAR V_OD_stat[64]= {0}; // Status SQL 执行sql语句的结果状态
SQLINTEGER V_OD_err = 0; // sql语句执行后的错误代码
SQLSMALLINT V_OD_mlen = 0; // 错误返回的消息文本大小
SQLCHAR V_OD_msg[256] = {0};// 错误消息缓冲区
char* pszBuf = NULL;
//清空缓冲区
Clear();
V_OD_erg=SQLExecDirect(V_OD_hstmt_, (SQLCHAR*)pszSQL, SQL_NTS);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
printf("Error in Select %d/n", V_OD_erg);
SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc_, 1, V_OD_stat, &V_OD_err, V_OD_msg, 256, &V_OD_mlen);
printf("%s (%d)/n",V_OD_msg, V_OD_err);
return 0;
}
//获取查询结果的数量
V_OD_erg = SQLRowCount(V_OD_hstmt_, &V_OD_rowanz_);
if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))
{
return 0;
}
return V_OD_rowanz_;
}
unsigned int CppODBC::SQLExecAutoID( char *pszSQL )
{
if ( pszSQL == NULL || pszIdField == NULL )
return 0;
//不同的数据库处理方法不同
//通用办法比较笨,需要增加自动增长字段的名字作为参数
unsigned long ulIdentiy = 0;
ulIdentiy = SQLExec( pszSQL );
if ( ulIdentiy == 0 )
return 0;
//获取插入操作的数据表
string str = pszSQL;
transform(str.begin(), str.end(), str.begin(), toupper);
int nLen1 = str.find("INTO");
int nLen2 = str.find("VALUES");
str = pszSQL;
nLen1 += strlen("INTO");
string str1 = str.substr(nLen1, nLen2-nLen1);
nLen1 = 0;
nLen1 = str1.find("(", 0);//从开始寻找左括号
if ( nLen1 > 0 )
str1 = str1.substr(0, nLen1);//消除带括号部分
str = "SELECT MAX(";
str += pszIdField;
str += ") FROM ";
str += str1;
ulIdentiy = SQLQuery(str.c_str());
ulIdentiy = GetIntValue(0);
return ulIdentiy;
}
bool CppODBC::IsOpen( )
{
return bOpened_;
}
//查询的结果数量,更新时返回更新的记录数量,删除时返回删除的数量
unsigned int CppODBC::GetCount( )
{
return V_OD_rowanz_;
}
//返回查询结果的列数两
unsigned int CppODBC::GetColumns( )
{
return V_OD_colanz_;
}
int CppODBC::GetIntValue( unsigned int uiIndex )
{
if ( uiIndex < 0 || uiIndex > V_OD_colanz_ )
return 0;
int nField = 0;
if (pszField_[uiIndex] != NULL)
nField = atoi( pszField_[uiIndex] );
nField = atoi( pszField_[uiIndex] );
return nField;
}
char * CppODBC::GetStrValue( unsigned int uiIndex )
{
if ( uiIndex < 0 || uiIndex > V_OD_colanz_ )
return NULL;
return pszField_[uiIndex];
}
//取消操作
bool CppODBC::Cancel( )
{
}
//获取错误代码
unsigned int CppODBC::GetError( )
{
}
//下一个
bool CppODBC::Next( )
{
long V_OD_erg = 0;
V_OD_erg = SQLFetch( V_OD_hstmt_ );
if ( V_OD_erg != SQL_NO_DATA )
bEof_ = false;
else
bEof_ = true;
return !bEof_;
}
bool CppODBC::Eof( )
{
return bEof_;
}
void CppODBC::Lock()
{
if (!mutex_inited_)
return ;
pthread_mutex_lock(&mutex_);
}
void CppODBC::UnLock()
{
if (!mutex_inited_)
return ;
pthread_mutex_unlock(&mutex_);
}
int main()
{
CppODBC cppOdbc;
bool bRes = cppOdbc.Open();
if ( !bRes )
{
printf ( "Open error!/n " );
return 0;
}
printf ( "Open OK!/n " );
bRes = cppOdbc.Connect("mysqlODBC", "lizp" , "lizp");
if ( !bRes )
{
printf ( "Connect error!/n " );
return 0;
}
printf ( "Connect OK!/n " );
int nRes = 0;
//INSERT INTO UserInfo VALUES('44', 'ODBCTest22')
nRes = cppOdbc.SQLExec( "UPDATE UserInfo SET UID='55' WHERE UID='44'" );
printf ( "SQLExec the nRes is %d/n", nRes );
nRes = cppOdbc.SQLQuery("SELECT UID,UName FROM UserInfo");
printf ( "SQLQuery the nRes is %d/n", nRes );
char *pszBuf = NULL;
int nBuf = 0;
int i = 0;
while( !cppOdbc.Eof() )
{
i = 0;
nBuf = cppOdbc.GetIntValue( i++ );
printf ( " UID is %d/n", nBuf );
//nBuf = cppOdbc.GetIntValue( i++ );
//printf ( " UID is %d/n", nBuf );
pszBuf = cppOdbc.GetStrValue( i++ );
printf ( " UName is %s/n", pszBuf );
cppOdbc.Next();
//getchar();
}
cppOdbc.DisConnect();
cppOdbc.Close();
return 0;
}