![]() |
Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members
Session.cppGo 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 |