1. 程式人生 > >cppodbc--c++的odbc封裝類

cppodbc--c++的odbc封裝類

近日閒暇時研究了一下linux下的開源專案unixodbc,使用起來很是方便。現在總結一下,以饗讀者。

關於ODBC的介紹,在網上找了一段比較經典的解釋:ODBC Open Database Connect 即開放資料庫互連的簡稱,它是由Microsoft 公司於1991 年提出的一個用於訪問資料庫的統一介面標準,是應用程式和資料庫系統之間的中介軟體。它通過使用相應應用平臺上和所需資料庫對應的驅動程式與應用程式的互動來實現對資料庫的操作,避免了在應用程式中直接呼叫與資料庫相關的操作,從而提供了資料庫的獨立性。

    ODBC 主要由驅動程式和驅動程式管理器組成。驅動程式是一個用以支援ODBC

函式呼叫的模組,每個驅動程式對應於相應的資料庫,當應用程式從基於一個數據庫系統移植到另一個時,只需更改應用程式中由ODBC 管理程式設定的與相應資料庫系統對應的別名即可。驅動程式管理器可連結到所有ODBC 應用程式中,它負責管理應用程式中ODBC 函式與DLL 中函式的繫結。

    ODBC 使用層次的方法來管理資料庫,在資料庫通訊結構的每一層,對可能出現依賴資料庫產品自身特性的地方,ODBC 都引入一個公共介面以解決潛在的不一致性,從而很好地解決了基於資料庫系統應用程式的相對獨立性,這也是ODBC 一經推出就獲得巨大成功的重要原因之一。

    unix下著名的ODBC專案有unixodbc

iodbc,其中iodbc最近有所更新,但是筆者嘗試安裝沒有成功。而且在Google上搜索這兩個關鍵字,unixodbc遠高於iodbc,所以筆者膚淺的認為unixodbc要比iodbc更加受歡迎。

安裝步驟:

tar zxvf unixODBC-2.2.14.tar.gz
cd unixODBC-2.2.14
./configure --prefix=/usr/local/unixODBC-2.2.14 --includedir=/usr/include --libdir=/usr/lib -bindir=/usr/bin --sysconfdir=/etc
make
make install

這時,unixodbc

已經安裝完畢,這時候可以使用odbc的通用api進行程式設計了。

安裝步驟:

tar zxvf mysql-5.1.38-linux-i686-icc-glibc23.tar.gz

cd mysql-connector-odbc-5.1.5-linux-x86-32bit

cp lib/* /usr/lib //把該目錄下所有的檔案拷貝到系統庫目錄下

./bin/myodbc-installer //會顯示怎麼建立資料來源

根據提示建立資料來源,會在/etc/下產生兩個檔案odbc.iniodbcinst.ini

其中 odbc.ini內容如下:

[test]

Driver= /usr/lib/libmyodbc5.so

SERVER= localhost

UID= root

PWD= root

DATABASE= mysql

PORT= 3306

odbcinst.ini內容如下:

[MySQL ODBC 5.1 Driver]

Driver= /usr/lib/myodbc5.so

SETUP= /usr/lib/myodbc3S.so

UsageCount= 1

到此,資料來源就建立了,通過下面的cppodbc封裝類,就可以對mysql資料庫進行操作了。

//.h

////////////////////////////////////////////////////////////////////////////////

// CppMysql - A C++ wrapper around the odbc interface library.

//

// Copyright (c) 2009 Rob Groves. All Rights Reserved. [email protected]

//

// Permission to use, copy, modify, and distribute this software and its

// documentation for any purpose, without fee, and without a written

// agreement, is hereby granted, provided that the above copyright notice,

// this paragraph and the following two paragraphs appear in all copies,

// modifications, and distributions.

//

// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,

// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST

// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,

// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//

// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT

// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A

// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF

// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION

// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

//

// if u use it, u should show the source

// by ben

//

// if u find some questions, please tell me with email

// [email protected]

//

// V1.120/09/2009-Initial Version for cppodbc

////////////////////////////////////////////////////////////////////////////////

#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:

boolOpen( );

boolClose( );

boolConnect( const char* pszDSN, const char* pszUName, const char* pszUPasswd );

boolDisConnect( );

boolClear( );

unsigned intSQLQuery( const char* pszSQL );

unsigned intSQLExec( const char* pszSQL );

unsigned intSQLExecAutoID( char *pszSQL );

boolIsOpen( );

//查詢的結果數量,更新時返回更新的記錄數量,刪除時返回刪除的數量

unsigned intGetCount( );

//返回查詢結果的列數兩

unsigned intGetColumns( );

intGetIntValue( unsigned int uiIndex );

char *GetStrValue( unsigned int uiIndex );

//取消操作

boolCancel( );

//獲取錯誤程式碼

longGetError( );

//下一個

boolNext( );

boolEof( );

boolLock();

boolUnLock();

private:

SQLHENVV_OD_Env_;// Handle ODBC environment 存放環境變數

SQLHDBCV_OD_hdbc_;// Handle connection 連線控制代碼

SQLHSTMTV_OD_hstmt_;// SQL語句的控制代碼

SQLINTEGERV_OD_rowanz_;// 操作影響的記錄數量

SQLSMALLINTV_OD_colanz_;// 操作影響的記錄包含的欄位數量

SQLINTEGERV_OD_err_;// sql語句執行後的錯誤程式碼

char*pszField_[FIELD_NUM];// 存放一條查詢結果集,緩衝區根據查詢結果建立

intnMaxFiledLen_;//欄位的最大值

boolbOpened_;

boolbConnected_;

boolbEof_;

pthread_mutex_t mutex_;

boolmutex_inited_;

};

#endif

//.cpp

////////////////////////////////////////////////////////////////////////////////

// CppMysql - A C++ wrapper around the odbc interface library.

//

// Copyright (c) 2009 Rob Groves. All Rights Reserved. [email protected]

//

// Permission to use, copy, modify, and distribute this software and its

// documentation for any purpose, without fee, and without a written

// agreement, is hereby granted, provided that the above copyright notice,

// this paragraph and the following two paragraphs appear in all copies,

// modifications, and distributions.

//

// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,

// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST

// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,

// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//

// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT

// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A

// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF

// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION

// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

//

// if u use it, u should show the source

// from http://rainfish.cublog.cn

// by ben

//

// if u find some questions, please tell me with email

// [email protected]

//

// V1.120/09/2009-Initial Version for cppodbc

////////////////////////////////////////////////////////////////////////////////

#include "cppodbc.h"

#include <string.h>

CppODBC::CppODBC( )

{

V_OD_err_ = 0;

bOpened_ = false;

bConnected_ = false;

nMaxFiledLen_ = 512;

bEof_ = false;

for(int i=0; i<FIELD_NUM; i++)

pszField_[i] = NULL;

mutex_inited_ = false;

//初始化互斥體

if ( !mutex_inited_ )

{

pthread_mutex_init(&mutex_, NULL);

mutex_inited_ = true;

}

}

CppODBC::~CppODBC( )

{

if (mutex_inited_)

pthread_mutex_destroy(&mutex_);

Clear( );

}

boolCppODBC::Open()

{

if ( bOpened_ )//已經打開了

return true;

longV_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;

}

bOpened_ = true;

return true;

}

boolCppODBC::Close( )

{

if ( bConnected_ )

return false;

SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env_);

bOpened_ = false;

return true;

}

boolCppODBC::Connect( const char* pszDSN, const char* pszUName, const char* pszUPasswd )

{

if ( !bOpened_ )

return false;

if ( pszDSN == NULL )

return false;

longV_OD_erg = 0;

SQLCHARV_OD_stat[64]= {0}; // Status SQL 執行sql語句的結果狀態

SQLSMALLINT V_OD_mlen = 0;// 錯誤返回的訊息文字大小

SQLCHARV_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 %ld/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 %ld/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 %ld/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 (%ld)/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 %ld/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 (%ld)/n", V_OD_msg, V_OD_err_);

SQLDisconnect( V_OD_hdbc_ );

SQLFreeHandle( SQL_HANDLE_DBC, V_OD_hdbc_ );

return false;