Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsdbfreetds.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #ifdef __ENABLE_FREETDS__
00034 
00035 #include "mmstools/mmsdbfreetds.h"
00036 #include "mmstools/mmstools.h"
00037 #include <stdlib.h>
00038 #include <string.h>
00039 
00040 /**
00041  * @file  mmsdbfreetds.cpp
00042  *
00043  * @brief Source file for freetds database functions.
00044  *
00045  * @ingroup mmstools
00046  */
00047 
00048 MMSDBFreeTDS::MMSDBFreeTDS(DataSource *_datasource) :
00049     dbhandle(NULL),
00050     henv(SQL_NULL_HENV),
00051     IMMSDB(_datasource) {
00052 
00053     if(!this->datasource) {
00054         throw MMSError(0, "Cannot instantiate MMSDBFreeTDS without datasource");
00055     }
00056 }
00057 
00058 MMSDBFreeTDS::~MMSDBFreeTDS() {
00059     this->disconnect();
00060 }
00061 
00062 /**
00063  * @brief Gets and creates a databases error message.
00064  *
00065  * @param   rc      return code of last called sql function
00066  * @param   htype   type of handle for which diagnostics should be run
00067  * @param   handle  database connection handle
00068  *
00069  * @return last error message.
00070  */
00071 string errmsg(SQLRETURN rc, SQLSMALLINT htype, SQLHANDLE handle) {
00072     SQLCHAR szSqlState[6],szErrorMsg[SQL_MAX_MESSAGE_LENGTH];
00073     SQLINTEGER pfNativeError;
00074     SQLSMALLINT pcbErrorMsg;
00075 
00076     rc = SQLGetDiagRec(htype, handle,1,
00077             (SQLCHAR *)&szSqlState,
00078             (SQLINTEGER *)&pfNativeError,
00079             (SQLCHAR *)&szErrorMsg,
00080             SQL_MAX_MESSAGE_LENGTH-1,
00081             (SQLSMALLINT *)&pcbErrorMsg);
00082 
00083     string msg = string((char*)szSqlState) + "|" + string((char*)szErrorMsg);
00084     DEBUGMSG("MMSFREETDS", msg);
00085 
00086     return msg;
00087 }
00088 
00089 void MMSDBFreeTDS::connect() {
00090     int rc;
00091     char connection_string[256] = "";
00092 
00093     if(this->connected) {
00094         DEBUGMSG("MMSFREETDS", "already connected");
00095         return;
00096     }
00097 
00098     if((rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &this->henv)) != SQL_SUCCESS) {
00099         throw MMSError(rc, "SQLAllocHandle() failed. [" + errmsg(rc,DIAG_TYPE_ENV, this->henv) +"]");
00100     }
00101 
00102     if((rc = SQLSetEnvAttr(this->henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,0)) != SQL_SUCCESS) {
00103         SQLFreeHandle(SQL_HANDLE_ENV, this->henv);
00104         throw MMSError(rc, "SQLSetEnvAttr() failed. [" + errmsg(rc,DIAG_TYPE_ENV, this->henv) +"]");
00105     }
00106 
00107     if((rc = SQLAllocHandle(SQL_HANDLE_DBC, this->henv, this->dbhandle)) != SQL_SUCCESS) {
00108         SQLFreeHandle(SQL_HANDLE_ENV, this->henv);
00109         throw MMSError(rc, "SQLAllocHandle() failed. [" + errmsg(rc,DIAG_TYPE_ENV, this->henv) +"]");
00110     }
00111 
00112     snprintf(connection_string,sizeof(connection_string),
00113             "Server=%s;UID=%s;PWD=%s;Database=%s;Port=%d;TDS_Version=8.0;",
00114             datasource->getAddress().c_str(),
00115             datasource->getUser().c_str(),
00116             datasource->getPassword().c_str(),
00117             datasource->getDatabaseName().c_str(),
00118             datasource->getPort());
00119 
00120     DEBUGMSG("MMSFREETDS", "try to connect to database: %s", connection_string);
00121 
00122     if((rc = SQLDriverConnect(*(this->dbhandle), NULL, (SQLCHAR *)connection_string, SQL_NTS,
00123                             (SQLCHAR *)connection_string,sizeof(connection_string),NULL, SQL_DRIVER_COMPLETE)) != SQL_SUCCESS) {
00124         SQLFreeHandle(SQL_HANDLE_DBC, *(this->dbhandle));
00125         this->dbhandle = NULL;
00126         SQLFreeHandle(SQL_HANDLE_ENV, this->henv);
00127         throw MMSError(rc, "SQLDriverConnect() failed. [" + errmsg(rc,DIAG_TYPE_ENV, this->henv) +"]");
00128     }
00129 
00130     this->connected = true;
00131 
00132     DEBUGMSG("MMSFREETDS", "connect to database successful");
00133 }
00134 
00135 void MMSDBFreeTDS::disconnect() {
00136     if(this->connected) {
00137         if(this->dbhandle) {
00138             SQLDisconnect(this->dbhandle);
00139             SQLFreeConnect(this->dbhandle);
00140             SQLFreeHandle(SQL_HANDLE_DBC, this->dbhandle);
00141         }
00142 
00143         if(this->henv != SQL_NULL_HENV) {
00144             SQLFreeHandle(SQL_HANDLE_ENV, this->henv);
00145         }
00146 
00147         this->connected = false;
00148     }
00149 }
00150 
00151 int MMSDBFreeTDS::query(string statement, MMSRecordSet *rs) {
00152     int             rc      = 0;
00153     SQLHSTMT        hstmt   = SQL_NULL_HSTMT;
00154     SQLSMALLINT     columns = 0;
00155     MMSRecordSet    *myrs   = (MMSRecordSet *)rs;
00156 
00157     myrs->reset();
00158     myrs->setRecordNum(0);
00159 
00160     query(statement, hstmt, false);
00161 
00162     int ret, rows=0;
00163 
00164     while (SQL_SUCCEEDED(ret = SQLFetch(hstmt))) {
00165         SQLUSMALLINT i;
00166 
00167         /* add a new row to resultset*/
00168         myrs->addRow();
00169         rows++;
00170 
00171         /* Loop through the columns */
00172         for (i = 1; i <= columns; i++) {
00173             SQLLEN indicator;
00174             char buf[512];
00175             SQLCHAR colname[32];
00176             SQLSMALLINT coltype;
00177             SQLSMALLINT colnamelen;
00178             SQLSMALLINT nullable;
00179             SQLSMALLINT scale;
00180             SQLULEN collen[1024];
00181 
00182             SQLDescribeCol (hstmt, i, colname, sizeof (colname),
00183                     &colnamelen, &coltype, &collen[i], &scale, &nullable);
00184 
00185             /* retrieve column data as a string */
00186             ret = SQLGetData(hstmt, i, SQL_C_CHAR, buf, sizeof(buf), &indicator);
00187             if (SQL_SUCCEEDED(ret)) {
00188                 /* Handle null columns */
00189                 if (indicator == SQL_NULL_DATA) strcpy(buf, "NULL");
00190 
00191                 (*myrs)[(char*)colname]=(char *)buf;
00192             }
00193         }
00194     }
00195 
00196     //rewind
00197     rs->setRecordNum(0);
00198 
00199     SQLCloseCursor(hstmt);
00200     SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00201 
00202     DEBUGMSG("MMSFREETDS", iToStr(rows) + " rows returned.");
00203 
00204     return rows;
00205 }
00206 
00207 int MMSDBFreeTDS::query(string statement) {
00208     SQLHSTMT hstmt = SQL_NULL_HSTMT;
00209 
00210     return query(statement, hstmt);
00211 }
00212 
00213 int MMSDBFreeTDS::query(string statement, SQLHSTMT &hstmt, bool finishStatement) {
00214     int rc = 0;
00215     SQLSMALLINT columns=0;
00216 
00217     // start the query
00218     if((rc = SQLAllocHandle(SQL_HANDLE_STMT, *this->dbhandle, &hstmt)) != SQL_SUCCESS) {
00219         throw MMSError(rc, "SQLAllocHandle() failed. [" + errmsg(rc,DIAG_TYPE_ENV, this->henv) +"]");
00220     }
00221 
00222     DEBUGMSG("MMSFREETDS", statement);
00223 
00224     // start a stored procedure
00225     if((rc = SQLExecDirect(hstmt, (SQLCHAR *) statement.c_str(), SQL_NTS)) != SQL_SUCCESS) {
00226         throw MMSError(rc, "Execution of query failed. [" + errmsg(rc, DIAG_TYPE_STMT, hstmt) +"]");
00227     }
00228 
00229     SQLNumResultCols(hstmt, &columns);
00230 
00231     if(finishStatement) {
00232         SQLCloseCursor(hstmt);
00233         SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00234     }
00235 
00236     return columns;
00237 }
00238 
00239 int MMSDBFreeTDS::executeSP(string spName, MMSDB_SP_ARGLIST argList, MMSRecordSet *rs) {
00240     string query;
00241     MMSDB_SP_ARGLIST::iterator it;
00242 
00243     //Build my query
00244     query="{" + string(FREETDS_SP_EXEC_CMD) + spName + " (";
00245 
00246     for(it = argList.begin();it!=argList.end();it++) {
00247         if(it!=argList.begin())
00248         query += ",";
00249 
00250         query += it->first + "=" + it->second;
00251     }
00252 
00253     query+=")}";
00254 
00255     return this->query(query, rs);
00256 }
00257 
00258 int MMSDBFreeTDS::executeSP(string spName, MMSDB_SP_ARGLIST argList) {
00259     string query;
00260     MMSDB_SP_ARGLIST::iterator it;
00261 
00262     //Build my query
00263     query="{" + string(FREETDS_SP_EXEC_CMD) + spName + " (";
00264 
00265     for(it = argList.begin();it!=argList.end();it++) {
00266         if(it!=argList.begin())
00267         query += ",";
00268 
00269         query += it->first + "=" + it->second;
00270     }
00271 
00272     query+=")}";
00273 
00274     return this->query(query);
00275 }
00276 
00277 #endif /*__ENABLE_FREETDS__*/

Generated by doxygen