Logo
~Database~
~ C++ ~
~Contact~

Session.cpp

Go to the documentation of this file.
00001 /*
00002  **     Session.cpp
00003  **
00004  **     Published / author: 2006-03-29 / grymse@alhem.net
00005  **/
00006 /*
00007 Copyright (C) 2006 Anders Hedstrom
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022 */
00023 #ifdef _WIN32
00024 #pragma warning(disable:4786)
00025 #endif
00026 
00027 #include <afxdb.h>
00028 #include <sql.h>
00029 
00030 #include "Session.h"
00031 #include "Database.h"
00032 #include "Query.h"
00033 
00034 
00035 #ifdef ODBCW_NAMESPACE
00036 namespace ODBCW_NAMESPACE {
00037 #endif
00038 
00039 SQLHENV Session::m_henv = NULL;
00040 
00041 
00042 Session::Session()
00043 :m_hdbc(NULL)
00044 ,m_bBusy(false)
00045 ,m_nLastError(0)
00046 {
00047 }
00048 
00049 
00050 Session::~Session()
00051 {
00052         Disconnect();
00053         // ? ref count?
00054         if (m_henv)
00055         {
00056                 SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
00057                 m_henv = NULL;
00058         }
00059 }
00060 
00061 
00062 int Session::Connect(Database& db,const std::string& driverstring)
00063 {
00064         SQLRETURN retcode;
00065         int value;
00066 
00067         if (!m_henv)
00068         {
00069                 // Allocate environment handle (ENV)
00070                 retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv);
00071                 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00072                 {
00073                         ShowErrorInfo(retcode, SQL_HANDLE_ENV, m_henv);
00074                 }
00075                 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00076                 {
00077                         db.error("Allocate environment handle (ENV) failed");
00078                         return -1;
00079                 }
00080 
00081                 // Set the ODBC version environment attribute
00082                 retcode = SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
00083                 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00084                 {
00085                         ShowErrorInfo(retcode, SQL_HANDLE_ENV, m_henv);
00086                 }
00087                 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00088                 {
00089                         db.error("Set the ODBC version environment attribute failed");
00090                         return -2;
00091                 }
00092         }
00093 
00094         // Allocate connection handle (DBC)
00095         retcode = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc);
00096         if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00097         {
00098                 ShowErrorInfo(retcode, SQL_HANDLE_DBC, m_hdbc);
00099         }
00100         if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00101         {
00102                 db.error("Allocate connection handle (DBC) failed");
00103                 return -3;
00104         }
00105 
00106         // Set login timeout to 5 seconds.
00107         value = 5;
00108         SQLSetConnectAttr(m_hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)&value, 0);
00109         if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00110         {
00111                 ShowErrorInfo(retcode, SQL_HANDLE_DBC, m_hdbc);
00112         }
00113 
00114         // Connect to data source
00115         {
00116                 unsigned char slask[1024];
00117                 SQLSMALLINT cbl = 0;
00118 
00119                 *slask = 0;
00120                 retcode = SQLDriverConnect(m_hdbc, NULL,
00121                         (unsigned char *)driverstring.c_str(), (SQLSMALLINT)driverstring.size(),
00122                         slask, 1024, &cbl, SQL_DRIVER_PROMPT);
00123 
00124                 if (cbl >= 0 && cbl < 1024)
00125                 {
00126                         slask[cbl] = 0;
00127                 }
00128 //              MessageBox(NULL, (const char *)slask, "SQLDriverConnect std::string", MB_OK);
00129 
00130                 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00131                 {
00132                         ShowErrorInfo(retcode, SQL_HANDLE_DBC, m_hdbc);
00133                 }
00134                 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00135                 {
00136                         db.error("Connect to data source failed");
00137                         db.error(driverstring);
00138                         return -4;
00139                 }
00140         }
00141 
00142         // TODO: SQLGetInfo - to get info about odbc driver capabilities
00143 
00144         return 0;
00145 }
00146 
00147 
00148 int Session::Connect(Database& db,const std::string& dsn,const std::string& user,const std::string& password)
00149 {
00150         SQLRETURN retcode;
00151         int value;
00152 
00153         if (!m_henv)
00154         {
00155                 // Allocate environment handle (ENV)
00156                 retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv);
00157                 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00158                 {
00159                         ShowErrorInfo(retcode, SQL_HANDLE_ENV, m_henv);
00160                 }
00161                 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00162                 {
00163                         db.error("Allocate environment handle (ENV) failed");
00164                         return -1;
00165                 }
00166 
00167                 // Set the ODBC version environment attribute
00168                 retcode = SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
00169                 if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00170                 {
00171                         ShowErrorInfo(retcode, SQL_HANDLE_ENV, m_henv);
00172                 }
00173                 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00174                 {
00175                         db.error("Set the ODBC version environment attribute failed");
00176                         return -2;
00177                 }
00178         }
00179 
00180         // Allocate connection handle (DBC)
00181         retcode = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc);
00182         if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00183         {
00184                 ShowErrorInfo(retcode, SQL_HANDLE_DBC, m_hdbc);
00185         }
00186         if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00187         {
00188                 db.error("Allocate connection handle (DBC) failed");
00189                 return -3;
00190         }
00191 
00192         // Set login timeout to 5 seconds.
00193         value = 5;
00194         SQLSetConnectAttr(m_hdbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)&value, 0);
00195         if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00196         {
00197                 ShowErrorInfo(retcode, SQL_HANDLE_DBC, m_hdbc);
00198         }
00199 
00200         // Connect to data source
00201         retcode = SQLConnect(m_hdbc,
00202                                                         (SQLCHAR*) dsn.c_str(), SQL_NTS,
00203                                                         (SQLCHAR*) user.c_str(), SQL_NTS,
00204                                                         (SQLCHAR*) password.c_str(), SQL_NTS);
00205 
00206         if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
00207         {
00208                 ShowErrorInfo(retcode, SQL_HANDLE_DBC, m_hdbc);
00209         }
00210         if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
00211         {
00212                 db.error("Connect to data source failed");
00213                 db.error(dsn);
00214                 return -4;
00215         }
00216 
00217         // TODO: SQLGetInfo - to get info about odbc driver capabilities
00218 
00219         return 0;
00220 }
00221 
00222 
00223 void Session::Disconnect()
00224 {
00225         if (m_hdbc)
00226         {
00227                 SQLDisconnect(m_hdbc);
00228                 SQLFreeHandle(SQL_HANDLE_DBC, m_hdbc);
00229                 m_hdbc = NULL;
00230         }
00231 }
00232 
00233 
00234 void *Session::GetHandle()
00235 {
00236         return m_hdbc;
00237 }
00238 
00239 
00240 void Session::SetBusy(bool b)
00241 {
00242         m_bBusy = b;
00243 }
00244 
00245 
00246 bool Session::IsBusy()
00247 {
00248         return m_bBusy;
00249 }
00250 
00251 int Session::GetLastError(std::string& strSqlState, std::string& strErrorMessage)
00252 {
00253         strSqlState = m_strLastErrorSqlState;
00254         strErrorMessage = m_strLastErrorMessage;
00255         return m_nLastError;
00256 }
00257 
00258 void Session::ResetLastError()
00259 {
00260         m_nLastError = 0;
00261         m_strLastErrorSqlState.empty();
00262         m_strLastErrorMessage.empty();
00263 }
00264 
00265 void Session::ShowErrorInfo(SQLRETURN rc, SQLSMALLINT hType, SQLHANDLE h)
00266 {
00267         SQLRETURN retcode;
00268         SQLSMALLINT iRecord = 1;
00269         SQLCHAR szSqlState[REM_LEN];
00270         SQLINTEGER pfNativeError;
00271         SQLCHAR szErrorMsg[REM_LEN];
00272         SQLSMALLINT cbErrorMsgMax = REM_LEN - 1;
00273         SQLSMALLINT pcbErrorMsg;
00274 
00275 /*
00276         printf("Handle type: %s\n", (hType == SQL_HANDLE_STMT) ? "Statement" :
00277                 (hType == SQL_HANDLE_ENV) ? "Environment" :
00278                 (hType == SQL_HANDLE_DBC) ? "DBC" : "???");*/
00279 
00280         retcode = SQLGetDiagRec (hType, h, // SQL_HANDLE_STMT, m_hstmt,
00281                 iRecord, szSqlState, &pfNativeError,
00282                 szErrorMsg, cbErrorMsgMax, &pcbErrorMsg);
00283 
00284 /*
00285         printf(" *** %s *** sqlstate '%s'       errormsg '%s'\n",
00286                 (rc == SQL_ERROR) ? "SQL_ERROR" :
00287                 (rc == SQL_SUCCESS_WITH_INFO) ? "SQL_SUCCESS_WITH_INFO" : "",
00288                 szSqlState, szErrorMsg);*/
00289 
00290         if (m_nLastError == 0)
00291         {
00292                 m_nLastError = rc;
00293                 m_strLastErrorSqlState = (char*)szSqlState;
00294                 m_strLastErrorMessage = (char*)szErrorMsg;
00295         }
00296 
00297 }
00298 
00299 
00300 #ifdef ODBCW_NAMESPACE
00301 } // namespace ODBCW_NAMESPACE {
00302 #endif
Page, code, and content Copyright (C) 2006 by Anders Hedström