context.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:14k
- /*
- * ===========================================================================
- * PRODUCTION $Log: context.cpp,v $
- * PRODUCTION Revision 1000.4 2004/06/01 19:21:44 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.14
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: context.cpp,v 1000.4 2004/06/01 19:21:44 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Author: Vladimir Soussov
- *
- * File Description: Driver for ODBC server
- *
- */
- #include <ncbi_pch.hpp>
- #include <corelib/ncbimtx.hpp>
- #include <dbapi/driver/odbc/interfaces.hpp>
- #include <dbapi/driver/util/numeric_convert.hpp>
- #ifdef HAVE_ODBCSS_H
- #include <odbcss.h>
- #endif
- BEGIN_NCBI_SCOPE
- /////////////////////////////////////////////////////////////////////////////
- //
- // CODBC_Reporter::
- //
- void CODBC_Reporter::ReportErrors()
- {
- SQLINTEGER NativeError;
- SQLSMALLINT MsgLen;
- SQLCHAR SqlState[6];
- SQLCHAR Msg[1024];
- if(!m_HStack) return;
- for(SQLSMALLINT i= 1; i < 128; i++) {
- switch(SQLGetDiagRec(m_HType, m_Handle, i, SqlState, &NativeError,
- Msg, sizeof(Msg), &MsgLen)) {
- case SQL_SUCCESS:
- if(strncmp((const char*)SqlState, "HYT", 3) == 0) { // timeout
- CDB_TimeoutEx to(NativeError, "odbc", (const char*)Msg);
- m_HStack->PostMsg(&to);
- }
- else if(strncmp((const char*)SqlState, "40001", 5) == 0) { // deadlock
- CDB_DeadlockEx dl("odbc", (const char*)Msg);
- m_HStack->PostMsg(&dl);
- }
- else if(NativeError != 5701 && NativeError != 5703){
- CDB_SQLEx se(eDB_Unknown, NativeError, "odbc", (const char*)Msg,
- (const char*)SqlState, 0);
- m_HStack->PostMsg(&se);
- }
- continue;
- case SQL_NO_DATA: break;
- case SQL_SUCCESS_WITH_INFO:
- {
- CDB_DSEx dse(eDB_Unknown, 777, "odbc", "Message is too long to be retrieved");
- m_HStack->PostMsg(&dse);
- }
- continue;
- default:
- {
- CDB_ClientEx ce(eDB_Warning, 420016, "CODBC_Reporter::ReportErrors",
- "SQLGetDiagRec failed (memory corruption suspected)");
- m_HStack->PostMsg(&ce);
- }
- break;
- }
- break;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // CODBCContext::
- //
- CODBCContext::CODBCContext(SQLINTEGER version, bool use_dsn) : m_Reporter(0, SQL_HANDLE_ENV, 0)
- {
- if(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_Context) != SQL_SUCCESS) {
- throw CDB_ClientEx(eDB_Fatal, 400001, "CODBCContext::CODBCContext",
- "Can not allocate a context");
- }
- m_Reporter.SetHandle(m_Context);
- m_Reporter.SetHandlerStack(&m_CntxHandlers);
- SQLSetEnvAttr(m_Context, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)version, 0);
-
-
- m_PacketSize= 0;
- m_LoginTimeout= 0;
- m_Timeout= 0;
- m_TextImageSize= 0;
- m_UseDSN= use_dsn;
- }
- bool CODBCContext::SetLoginTimeout(unsigned int nof_secs)
- {
- m_LoginTimeout= (SQLUINTEGER)nof_secs;
- return true;
- }
- bool CODBCContext::SetTimeout(unsigned int nof_secs)
- {
- m_Timeout= (SQLUINTEGER)nof_secs;
- for (int i = m_NotInUse.NofItems(); i--;) {
- CODBC_Connection* t_con
- = static_cast<CODBC_Connection*> (m_NotInUse.Get(i));
- t_con->ODBC_SetTimeout(m_Timeout);
- }
- for (int i = m_InUse.NofItems(); i--;) {
- CODBC_Connection* t_con
- = static_cast<CODBC_Connection*> (m_NotInUse.Get(i));
- t_con->ODBC_SetTimeout(m_Timeout);
- }
- return true;
- }
- bool CODBCContext::SetMaxTextImageSize(size_t nof_bytes)
- {
- m_TextImageSize = (SQLUINTEGER) nof_bytes;
- for (int i = m_NotInUse.NofItems(); i--;) {
- CODBC_Connection* t_con
- = static_cast<CODBC_Connection*> (m_NotInUse.Get(i));
- t_con->ODBC_SetTextImageSize(m_TextImageSize);
- }
-
- for (int i = m_InUse.NofItems(); i--;) {
- CODBC_Connection* t_con
- = static_cast<CODBC_Connection*> (m_NotInUse.Get(i));
- t_con->ODBC_SetTextImageSize(m_TextImageSize);
- }
- return true;
- }
- CDB_Connection* CODBCContext::Connect(const string& srv_name,
- const string& user_name,
- const string& passwd,
- TConnectionMode mode,
- bool reusable,
- const string& pool_name)
- {
- // static CFastMutex xMutex;
- CFastMutexGuard mg(m_Mtx);
- if (reusable && m_NotInUse.NofItems() > 0) {
- // try to get a connection from the pot
- if ( !pool_name.empty() ) {
- // use a pool name
- for (int i = m_NotInUse.NofItems(); i--; ) {
- CODBC_Connection* t_con
- = static_cast<CODBC_Connection*> (m_NotInUse.Get(i));
- if (pool_name.compare(t_con->PoolName()) == 0) {
- m_NotInUse.Remove(i);
- if(t_con->Refresh()) {
- m_InUse.Add((TPotItem) t_con);
- return Create_Connection(*t_con);
- }
- delete t_con;
- }
- }
- }
- else {
- if ( srv_name.empty() )
- return 0;
-
- // try to use a server name
- for (int i = m_NotInUse.NofItems(); i--; ) {
- CODBC_Connection* t_con
- = static_cast<CODBC_Connection*> (m_NotInUse.Get(i));
-
- if (srv_name.compare(t_con->ServerName()) == 0) {
- m_NotInUse.Remove(i);
- if(t_con->Refresh()) {
- m_InUse.Add((TPotItem) t_con);
- return Create_Connection(*t_con);
- }
- delete t_con;
- }
- }
- }
- }
- if((mode & fDoNotConnect) != 0) return 0;
- // new connection needed
- if (srv_name.empty() || user_name.empty() || passwd.empty()) {
- throw CDB_ClientEx(eDB_Error, 100010, "CODBCContext::Connect",
- "You have to provide server name, user name and "
- "password to connect to the server");
- }
- SQLHDBC con = x_ConnectToServer(srv_name, user_name, passwd, mode);
- if (con == 0) {
- throw CDB_ClientEx(eDB_Error, 100011, "CODBCContext::Connect",
- "Cannot connect to the server");
- }
- CODBC_Connection* t_con = new CODBC_Connection(this, con, reusable, pool_name);
- t_con->m_MsgHandlers = m_ConnHandlers;
- t_con->m_Server = srv_name;
- t_con->m_User = user_name;
- t_con->m_Passwd = passwd;
- // t_con->m_BCPAble = (mode & fBcpIn) != 0;
- t_con->m_SecureLogin = (mode & fPasswordEncrypted) != 0;
- m_InUse.Add((TPotItem) t_con);
- return Create_Connection(*t_con);
- }
- CODBCContext::~CODBCContext()
- {
- if ( !m_Context ) {
- return;
- }
- // close all connections first
- for (int i = m_NotInUse.NofItems(); i--; ) {
- CODBC_Connection* t_con = static_cast<CODBC_Connection*>(m_NotInUse.Get(i));
- delete t_con;
- }
- for (int i = m_InUse.NofItems(); i--; ) {
- CODBC_Connection* t_con = static_cast<CODBC_Connection*> (m_InUse.Get(i));
- delete t_con;
- }
- SQLFreeHandle(SQL_HANDLE_ENV, m_Context);
- }
- void CODBCContext::ODBC_SetPacketSize(SQLUINTEGER packet_size)
- {
- m_PacketSize = packet_size;
- }
- SQLHENV CODBCContext::ODBC_GetContext() const
- {
- return m_Context;
- }
- SQLHDBC CODBCContext::x_ConnectToServer(const string& srv_name,
- const string& user_name,
- const string& passwd,
- TConnectionMode mode)
- {
- SQLHDBC con;
- SQLRETURN r;
- r= SQLAllocHandle(SQL_HANDLE_DBC, m_Context, &con);
- if((r != SQL_SUCCESS) && (r != SQL_SUCCESS_WITH_INFO))
- return 0;
- if(m_Timeout) {
- SQLSetConnectAttr(con, SQL_ATTR_CONNECTION_TIMEOUT, (void*)m_Timeout, 0);
- }
-
- if(m_LoginTimeout) {
- SQLSetConnectAttr(con, SQL_ATTR_LOGIN_TIMEOUT, (void*)m_LoginTimeout, 0);
- }
-
- if(m_PacketSize) {
- SQLSetConnectAttr(con, SQL_ATTR_PACKET_SIZE, (void*)m_PacketSize, 0);
- }
-
- #ifdef SQL_COPT_SS_BCP
- if((mode & fBcpIn) != 0) {
- SQLSetConnectAttr(con, SQL_COPT_SS_BCP, (void*) SQL_BCP_ON, SQL_IS_INTEGER);
- }
- #endif
- if(!m_UseDSN) {
- #ifdef NCBI_OS_MSWIN
- string connect_str("DRIVER={SQL Server};SERVER=");
- #else
- string connect_str("DSN=");
- #endif
- connect_str+= srv_name;
- connect_str+= ";UID=";
- connect_str+= user_name;
- connect_str+= ";PWD=";
- connect_str+= passwd;
- r= SQLDriverConnect(con, 0, (SQLCHAR*) connect_str.c_str(), SQL_NTS,
- 0, 0, 0, SQL_DRIVER_NOPROMPT);
- }
- else {
- r= SQLConnect(con, (SQLCHAR*) srv_name.c_str(), SQL_NTS,
- (SQLCHAR*) user_name.c_str(), SQL_NTS,
- (SQLCHAR*) passwd.c_str(), SQL_NTS);
- }
- switch(r) {
- case SQL_SUCCESS_WITH_INFO:
- xReportConError(con);
- case SQL_SUCCESS: return con;
-
- case SQL_ERROR:
- xReportConError(con);
- SQLFreeHandle(SQL_HANDLE_DBC, con);
- break;
- default:
- m_Reporter.ReportErrors();
- break;
- }
-
- return 0;
- }
- void CODBCContext::xReportConError(SQLHDBC con)
- {
- m_Reporter.SetHandleType(SQL_HANDLE_DBC);
- m_Reporter.SetHandle(con);
- m_Reporter.ReportErrors();
- m_Reporter.SetHandleType(SQL_HANDLE_ENV);
- m_Reporter.SetHandle(m_Context);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Miscellaneous
- //
- ///////////////////////////////////////////////////////////////////////
- // Driver manager related functions
- //
- I_DriverContext* ODBC_CreateContext(map<string,string>* attr = 0)
- {
- SQLINTEGER version= SQL_OV_ODBC3;
- bool use_dsn= false;
- if(attr) {
- string vers= (*attr)["version"];
- if(vers.find("3") != string::npos)
- version= SQL_OV_ODBC3;
- else if(vers.find("2") != string::npos)
- version= SQL_OV_ODBC2;
- use_dsn= (*attr)["use_dsn"] == "true";
- }
- CODBCContext* cntx= new CODBCContext(version, use_dsn);
- if(cntx && attr) {
- string page_size= (*attr)["packet"];
- if(!page_size.empty()) {
- SQLUINTEGER s= atoi(page_size.c_str());
- cntx->ODBC_SetPacketSize(s);
- }
- }
- return cntx;
- }
- NCBI_DBAPIDRIVER_ODBC_EXPORT
- void DBAPI_RegisterDriver_ODBC(I_DriverMgr& mgr)
- {
- mgr.RegisterDriver("odbc", ODBC_CreateContext);
- }
- extern "C" {
- NCBI_DBAPIDRIVER_ODBC_EXPORT
- void* DBAPI_E_odbc()
- {
- return (void*)DBAPI_RegisterDriver_ODBC;
- }
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: context.cpp,v $
- * Revision 1000.4 2004/06/01 19:21:44 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.14
- *
- * Revision 1.14 2004/05/17 21:16:05 gorelenk
- * Added include of PCH ncbi_pch.hpp
- *
- * Revision 1.13 2004/04/07 13:41:48 gorelenk
- * Added export prefix to implementations of DBAPI_E_* functions.
- *
- * Revision 1.12 2004/03/17 19:25:38 gorelenk
- * Added NCBI_DBAPIDRIVER_ODBC_EXPORT export prefix for definition of
- * DBAPI_RegisterDriver_ODBC .
- *
- * Revision 1.11 2003/11/14 20:46:51 soussov
- * implements DoNotConnect mode
- *
- * Revision 1.10 2003/10/27 17:00:53 soussov
- * adds code to prevent the return of broken connection from the pool
- *
- * Revision 1.9 2003/07/21 21:58:08 soussov
- * fixes bug whith pool name mismatch in Connect()
- *
- * Revision 1.8 2003/07/18 19:20:34 soussov
- * removes SetPacketSize function
- *
- * Revision 1.7 2003/07/17 20:47:10 soussov
- * connections pool improvements
- *
- * Revision 1.6 2003/05/08 20:48:33 soussov
- * adding datadirect-odbc type of connecting string. Rememner that you need ODBCINI environment variable to make it works
- *
- * Revision 1.5 2003/05/05 20:48:29 ucko
- * Check HAVE_ODBCSS_H; fix some typos in an error message.
- *
- * Revision 1.4 2003/04/01 21:51:17 soussov
- * new attribute 'packet=XXX' (where XXX is a packet size) added to ODBC_CreateContext
- *
- * Revision 1.3 2002/07/03 21:48:50 soussov
- * adds DSN support if needed
- *
- * Revision 1.2 2002/07/02 20:52:54 soussov
- * adds RegisterDriver for ODBC
- *
- * Revision 1.1 2002/06/18 22:06:24 soussov
- * initial commit
- *
- *
- * ===========================================================================
- */