Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members  

odbc++/types.h

00001 /*
00002    This file is part of libodbc++.
00003 
00004    Copyright (C) 1999-2000 Manush Dodunekov <manush@stendahls.net>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.  If not, write to
00018    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.
00020 */
00021 
00022 #ifndef __ODBCXX_TYPES_H
00023 #define __ODBCXX_TYPES_H
00024 
00025 #include <odbc++/setup.h>
00026 
00027 #include <exception>
00028 
00029 #if !defined(ODBCXX_QT)
00030 # include <string>
00031 # else
00032 # include <qstring.h>
00033 #endif
00034 
00035 #include <ctime>
00036 #if defined(ODBCXX_NO_STD_TIME_T)
00037 namespace std {
00038   using ::time_t;
00039 };
00040 #endif
00041 
00042 #if defined(ODBCXX_QT)
00043 class QIODevice;
00044 #endif
00045 
00046 #if defined(ODBCXX_HAVE_ISQL_H) && defined(ODBCXX_HAVE_ISQLEXT_H)
00047 # include <isql.h>
00048 # include <isqlext.h>
00049 #elif defined(ODBCXX_HAVE_SQL_H) && defined(ODBCXX_HAVE_SQLEXT_H)
00050 # include <sql.h>
00051 # include <sqlext.h>
00052 #else
00053 # error "Whoops. Can not recognize the ODBC subsystem."
00054 #endif
00055 
00056 #if defined(ODBCXX_HAVE_SQLUCODE_H)
00057 # include <sqlucode.h>
00058 #endif
00059 
00060 // fixups for current iODBC, which kindly doesn't provide SQL_TRUE and
00061 // SQL_FALSE macros
00062 
00063 #if !defined(SQL_TRUE)
00064 # define SQL_TRUE 1
00065 #endif
00066 
00067 #if !defined(SQL_FALSE)
00068 # define SQL_FALSE 0
00069 #endif
00070 
00071 // MS ODBC SDK misses this in some releases
00072 #if ODBCVER >= 0x0300 && !defined(SQL_NOT_DEFERRABLE)
00073 # define SQL_NOT_DEFERRABLE 7
00074 #endif
00075 
00076 
00077 // Setup our ODBC3_C (odbc3 conditional) macro
00078 #if ODBCVER >= 0x0300
00079 
00080 # define ODBC3_C(odbc3_value,old_value) odbc3_value
00081 
00082 #else
00083 
00084 # define ODBC3_C(odbc3_value,old_value) old_value
00085 
00086 #endif
00087 
00088 
00089 // ODBC3_DC (odbc3 dynamic conditional)
00090 // Every context using this macro should provide
00091 // a this->_getDriverInfo() method returning
00092 // a const DriverInfo*
00093 
00094 #if ODBCVER >= 0x0300
00095 
00096 # define ODBC3_DC(odbc3_value,old_value) \
00097 (this->_getDriverInfo()->getMajorVersion()>=3?odbc3_value:old_value)
00098 
00099 #else
00100 
00101 # define ODBC3_DC(odbc3_value,old_value) old_value
00102 
00103 #endif
00104 
00105 #if defined(ODBCXX_HAVE_INTTYPES_H)
00106 # include <inttypes.h>
00107 #endif
00108 
00109 #include <vector>
00110 
00111 
00112 namespace odbc {
00113 
00114   // We want Long to be at least 64 bits
00115 
00116 #if defined(WIN32)
00117 
00118   typedef __int64 Long;
00119 
00120 #elif defined(ODBCXX_HAVE_INTTYPES_H)
00121 
00122   typedef int64_t Long;
00123 
00124 #else
00125 
00126 # if ODBCXX_SIZEOF_INT == 8
00127 
00128   typedef int Long;
00129 
00130 # elif ODBCXX_SIZEOF_LONG == 8
00131 
00132   typedef long Long;
00133 
00134 # elif ODBCXX_SIZEOF_LONG_LONG == 8
00135 
00136   typedef long long Long;
00137 
00138 # else
00139 
00140 #  error "Can't find an appropriate at-least-64-bit integer"
00141 
00142 # endif
00143 
00144 #endif
00145 
00146 
00147   //constants:
00148   //how much we try to fetch with each SQLGetData call
00149   const int GETDATA_CHUNK_SIZE=4*1024;
00150   //how much we write with each SQLPutData call
00151   const int PUTDATA_CHUNK_SIZE=GETDATA_CHUNK_SIZE;
00152 
00153   //how much we read/write in string<->stream conversion
00154   //better names for those?
00155   const int STRING_TO_STREAM_CHUNK_SIZE=1024;
00156   const int STREAM_TO_STRING_CHUNK_SIZE=STRING_TO_STREAM_CHUNK_SIZE;
00157 
00158 
00159 
00160 
00161 
00164   struct Types {
00167     enum SQLType {
00169       BIGINT            = SQL_BIGINT,
00171       BINARY            = SQL_BINARY,
00173       BIT               = SQL_BIT,
00175       CHAR              = SQL_CHAR,
00177       DATE              = ODBC3_C(SQL_TYPE_DATE,SQL_DATE),
00179       DECIMAL           = SQL_DECIMAL,
00181       DOUBLE            = SQL_DOUBLE,
00183       FLOAT             = SQL_FLOAT,
00185       INTEGER           = SQL_INTEGER,
00187       LONGVARBINARY     = SQL_LONGVARBINARY,
00189       LONGVARCHAR       = SQL_LONGVARCHAR,
00191       NUMERIC           = SQL_NUMERIC,
00193       REAL              = SQL_REAL,
00195       SMALLINT          = SQL_SMALLINT,
00197       TIME              = ODBC3_C(SQL_TYPE_TIME,SQL_TIME),
00199       TIMESTAMP         = ODBC3_C(SQL_TYPE_TIMESTAMP,SQL_TIMESTAMP),
00201       TINYINT           = SQL_TINYINT,
00203       VARBINARY         = SQL_VARBINARY,
00205       VARCHAR           = SQL_VARCHAR
00206 #if defined(ODBCXX_HAVE_SQLUCODE_H)
00207       ,
00209       WCHAR         = SQL_WCHAR,
00211       WVARCHAR      = SQL_WVARCHAR,
00213       WLONGVARCHAR   = SQL_WLONGVARCHAR
00214 #endif
00215     };
00216   };
00217 
00218 
00219 #if !defined(ODBCXX_QT)
00220 
00226   class ODBCXX_EXPORT Bytes {
00227   private:
00228     struct Rep {
00229       ODBCXX_SIGNED_CHAR_TYPE* buf_;
00230       size_t len_;
00231       int refCount_;
00232       Rep(const ODBCXX_SIGNED_CHAR_TYPE* b, size_t l)
00233         :len_(l), refCount_(0) {
00234         if(len_>0) {
00235           buf_=new ODBCXX_SIGNED_CHAR_TYPE[len_];
00236           memcpy((void*)buf_,(void*)b,len_);
00237         } else {
00238           buf_=NULL;
00239         }
00240       }
00241       ~Rep() {
00242         delete [] buf_;
00243       }
00244     };
00245 
00246     Rep* rep_;
00247   public:
00249     Bytes()
00250       :rep_(new Rep(NULL,0)) {
00251       rep_->refCount_++;
00252     }
00253 
00255     Bytes(const ODBCXX_SIGNED_CHAR_TYPE* data, size_t dataLen)
00256       :rep_(new Rep(data,dataLen)) {
00257       rep_->refCount_++;
00258     }
00259 
00261     Bytes(const Bytes& b)
00262       :rep_(b.rep_) {
00263       rep_->refCount_++;
00264     }
00265 
00267     Bytes& operator=(const Bytes& b) {
00268       if(--rep_->refCount_==0) {
00269         delete rep_;
00270       }
00271       rep_=b.rep_;
00272       rep_->refCount_++;
00273       return *this;
00274     }
00275 
00277     bool operator==(const Bytes& b) const {
00278                         if (getSize()!=b.getSize())
00279                                 return false;
00280                         for(size_t i=0;i<getSize();i++) {
00281                                 if(*(getData()+i)!=*(b.getData()+i))
00282                                         return false;
00283                         }
00284       return true;
00285     }
00286 
00288     ~Bytes() {
00289       if(--rep_->refCount_==0) {
00290         delete rep_;
00291       }
00292     }
00293 
00295     const ODBCXX_SIGNED_CHAR_TYPE* getData() const {
00296       return rep_->buf_;
00297     }
00298 
00300     size_t getSize() const {
00301       return rep_->len_;
00302     }
00303   };
00304 #endif
00305 
00307   class ODBCXX_EXPORT Date {
00308   protected:
00309     int year_;
00310     int month_;
00311     int day_;
00312 
00313     virtual void _invalid(const ODBCXX_CHAR_TYPE* what, int value);
00314 
00315     int _validateYear(int y) {
00316       return y;
00317     }
00318 
00319     int _validateMonth(int m) {
00320       if(m<1 || m>12) {
00321         this->_invalid(ODBCXX_STRING_CONST("month"),m);
00322       }
00323       return m;
00324     }
00325 
00326     int _validateDay(int d) {
00327       if(d<1 || d>31) {
00328         this->_invalid(ODBCXX_STRING_CONST("day"),d);
00329       }
00330       return d;
00331     }
00332 
00333   public:
00336     Date(int year, int month, int day) {
00337       this->setYear(year);
00338       this->setMonth(month);
00339       this->setDay(day);
00340     }
00341 
00346     explicit Date();
00347 
00352     Date(std::time_t t) {
00353       this->setTime(t);
00354     }
00355 
00360     Date(const ODBCXX_STRING& str) {
00361       this->parse(str);
00362     }
00363 
00365     Date(const Date& d)
00366       :year_(d.year_),
00367        month_(d.month_),
00368        day_(d.day_) {}
00369 
00371     Date& operator=(const Date& d) {
00372       year_=d.year_;
00373       month_=d.month_;
00374       day_=d.day_;
00375       return *this;
00376     }
00377 
00379     virtual ~Date() {}
00380 
00382     virtual void setTime(std::time_t t);
00383 
00385     std::time_t getTime() const;
00386 
00388     void parse(const ODBCXX_STRING& str);
00389 
00391     int getYear() const {
00392       return year_;
00393     }
00394 
00396     int getMonth() const {
00397       return month_;
00398     }
00399 
00401     int getDay() const {
00402       return day_;
00403     }
00404 
00406     void setYear(int year) {
00407       year_=this->_validateYear(year);
00408     }
00409 
00411     void setMonth(int month) {
00412       month_=this->_validateMonth(month);
00413     }
00414 
00416     void setDay(int day) {
00417       day_=this->_validateDay(day);
00418     }
00419 
00421     virtual ODBCXX_STRING toString() const;
00422   };
00423 
00425   class ODBCXX_EXPORT Time {
00426   protected:
00427     int hour_;
00428     int minute_;
00429     int second_;
00430 
00431     virtual void _invalid(const ODBCXX_CHAR_TYPE* what, int value);
00432 
00433     int _validateHour(int h) {
00434       if(h<0 || h>23) {
00435         this->_invalid(ODBCXX_STRING_CONST("hour"),h);
00436       }
00437       return h;
00438     }
00439 
00440     int _validateMinute(int m) {
00441       if(m<0 || m>59) {
00442         this->_invalid(ODBCXX_STRING_CONST("minute"),m);
00443       }
00444       return m;
00445     }
00446 
00447     int _validateSecond(int s) {
00448       if(s<0 || s>61) {
00449         this->_invalid(ODBCXX_STRING_CONST("second"),s);
00450       }
00451       return s;
00452     }
00453 
00454   public:
00456     Time(int hour, int minute, int second) {
00457       this->setHour(hour);
00458       this->setMinute(minute);
00459       this->setSecond(second);
00460     }
00461 
00466     explicit Time();
00467 
00472     Time(std::time_t t) {
00473       this->setTime(t);
00474     }
00475 
00480     Time(const ODBCXX_STRING& str) {
00481       this->parse(str);
00482     }
00483 
00485     Time(const Time& t)
00486       :hour_(t.hour_),
00487        minute_(t.minute_),
00488        second_(t.second_) {}
00489 
00491     Time& operator=(const Time& t) {
00492       hour_=t.hour_;
00493       minute_=t.minute_;
00494       second_=t.second_;
00495       return *this;
00496     }
00497 
00499     virtual ~Time() {}
00500 
00502     virtual void setTime(std::time_t t);
00503 
00505     std::time_t getTime() const;
00506 
00508     void parse(const ODBCXX_STRING& str);
00509 
00511     int getHour() const {
00512       return hour_;
00513     }
00514 
00516     int getMinute() const {
00517       return minute_;
00518     }
00519 
00521     int getSecond() const {
00522       return second_;
00523     }
00524 
00526     void setHour(int h) {
00527       hour_=this->_validateHour(h);
00528     }
00529 
00531     void setMinute(int m) {
00532       minute_=this->_validateMinute(m);
00533     }
00534 
00536     void setSecond(int s) {
00537       second_=this->_validateSecond(s);
00538     }
00539 
00540     virtual ODBCXX_STRING toString() const;
00541   };
00542 
00543 
00546   class ODBCXX_EXPORT Timestamp : public Date, public Time {
00547   private:
00548     int nanos_;
00549 
00550     virtual void _invalid(const ODBCXX_CHAR_TYPE* what, int value);
00551 
00552     int _validateNanos(int n) {
00553       if(n<0) {
00554         this->_invalid(ODBCXX_STRING_CONST("nanoseconds"),n);
00555       }
00556       return n;
00557     }
00558 
00559   public:
00561     Timestamp(int year, int month, int day,
00562               int hour, int minute, int second,
00563               int nanos =0)
00564       :Date(year,month,day), Time(hour,minute,second) {
00565       this->setNanos(nanos);
00566     }
00567 
00572     explicit Timestamp();
00573 
00578     Timestamp(std::time_t t) {
00579       this->setTime(t);
00580     }
00581 
00586     Timestamp(const ODBCXX_STRING& s) {
00587       this->parse(s);
00588     }
00589 
00590 
00592     Timestamp(const Timestamp& t)
00593       :Date(t),Time(t),nanos_(t.nanos_) {}
00594 
00596     Timestamp& operator=(const Timestamp& t) {
00597       Date::operator=(t);
00598       Time::operator=(t);
00599       nanos_=t.nanos_;
00600       return *this;
00601     }
00602 
00604     virtual ~Timestamp() {}
00605 
00607     virtual void setTime(std::time_t t);
00608 
00610     virtual std::time_t getTime() {
00611       return Date::getTime()+Time::getTime();
00612     }
00613 
00616     void parse(const ODBCXX_STRING& s);
00617 
00619     int getNanos() const {
00620       return nanos_;
00621     }
00622 
00624     void setNanos(int nanos) {
00625       nanos_=this->_validateNanos(nanos);
00626     }
00627 
00628     virtual ODBCXX_STRING toString() const;
00629   };
00630 
00631 
00632   //this is used for several 'lists of stuff' below
00633   //expects T to be a pointer-to-something, and
00634   //the contents will get deleted when the vector
00635   //itself is deleted
00636   template <class T> class CleanVector : public std::vector<T> {
00637   private:
00638     CleanVector(const CleanVector<T>&); //forbid
00639     CleanVector<T>& operator=(const CleanVector<T>&); //forbid
00640 
00641   public:
00642     explicit CleanVector() {}
00643     virtual ~CleanVector() {
00644       typename std::vector<T>::iterator i=this->begin();
00645       typename std::vector<T>::iterator end=this->end();
00646       while(i!=end) {
00647         delete *i;
00648         ++i;
00649       }
00650       this->clear();
00651     }
00652   };
00653 
00654 
00657   class ODBCXX_EXPORT DriverMessage {
00658     friend class ErrorHandler;
00659 
00660   private:
00661     ODBCXX_CHAR_TYPE state_[SQL_SQLSTATE_SIZE+1];
00662     ODBCXX_CHAR_TYPE description_[SQL_MAX_MESSAGE_LENGTH];
00663     SQLINTEGER nativeCode_;
00664 
00665     DriverMessage() {}
00666 #if ODBCVER < 0x0300
00667     static DriverMessage* fetchMessage(SQLHENV henv,
00668                                        SQLHDBC hdbc,
00669                                        SQLHSTMT hstmt);
00670 #else
00671     static DriverMessage* fetchMessage(SQLINTEGER handleType,
00672                                        SQLHANDLE h,
00673                                        int idx);
00674 #endif
00675 
00676   public:
00677     virtual ~DriverMessage() {}
00678 
00679     const ODBCXX_CHAR_TYPE* getSQLState() const {
00680       return state_;
00681     }
00682 
00683     const ODBCXX_CHAR_TYPE* getDescription() const {
00684       return description_;
00685     }
00686 
00687     int getNativeCode() const {
00688       return nativeCode_;
00689     }
00690   };
00691 
00692 
00695   class SQLException : public std::exception {
00696   private:
00697     ODBCXX_STRING reason_;
00698     ODBCXX_STRING sqlState_;
00699     int errorCode_;
00700 #if defined(ODBCXX_UNICODE)
00701     std::string reason8_;
00702 #elif defined(ODBCXX_QT)
00703     QCString reason8_;
00704 #endif
00705   public:
00707     SQLException(const ODBCXX_STRING& reason =ODBCXX_STRING_CONST(""),
00708                  const ODBCXX_STRING& sqlState =ODBCXX_STRING_CONST(""),
00709                  int vendorCode =0)
00710       :reason_(reason),
00711        sqlState_(sqlState),
00712        errorCode_(vendorCode)
00713 #if defined(ODBCXX_UNICODE)
00714 {
00715    const size_t length =sizeof(wchar_t)*reason_.size();
00716    char* temp =new char[length+1];
00717    wcstombs(temp,reason_.c_str(),length);
00718    reason8_ =temp;
00719    delete[] temp;
00720 }
00721 #else
00722 # if defined(ODBCXX_QT)
00723       ,reason8_(reason.local8Bit())
00724 # endif
00725 {}
00726 #endif
00727 
00729     SQLException(const DriverMessage& dm)
00730       :reason_(dm.getDescription()),
00731        sqlState_(dm.getSQLState()),
00732        errorCode_(dm.getNativeCode()) {}
00733 
00735     virtual ~SQLException() throw() {}
00736 
00738     int getErrorCode() const {
00739       return errorCode_;
00740     }
00741 
00746     const ODBCXX_STRING& getSQLState() const {
00747       return sqlState_;
00748     }
00749 
00751     const ODBCXX_STRING& getMessage() const {
00752       return reason_;
00753     }
00754 
00755 
00757     virtual const char* what() const throw() {
00758       // the conversion from QString involves a temporary, which
00759       // doesn't survive this scope. So here, we do a conditional
00760 #if defined(ODBCXX_QT)
00761       return reason8_.data();
00762 #else
00763 # if defined(ODBCXX_UNICODE)
00764       return reason8_.c_str();
00765 # else
00766       return reason_.c_str();
00767 # endif
00768 #endif
00769     }
00770   };
00771 
00772 
00777   class SQLWarning : public SQLException {
00778 
00779     SQLWarning(const SQLWarning&); //forbid
00780     SQLWarning& operator=(const SQLWarning&); //forbid
00781 
00782   public:
00784     SQLWarning(const ODBCXX_STRING& reason = ODBCXX_STRING_CONST(""),
00785                const ODBCXX_STRING& sqlState = ODBCXX_STRING_CONST(""),
00786                int vendorCode =0)
00787       :SQLException(reason,sqlState,vendorCode) {}
00788 
00790     SQLWarning(const DriverMessage& dm)
00791       :SQLException(dm) {}
00792 
00794     virtual ~SQLWarning() throw() {}
00795   };
00796 
00797   typedef CleanVector<SQLWarning*> WarningList;
00798 
00799 
00800   template <class T> class Deleter {
00801   private:
00802     T* ptr_;
00803     bool isArray_;
00804 
00805     Deleter(const Deleter<T>&);
00806     Deleter<T>& operator=(const Deleter<T>&);
00807 
00808   public:
00809     explicit Deleter(T* ptr, bool isArray =false)
00810       :ptr_(ptr), isArray_(isArray) {}
00811     ~Deleter() {
00812       if(!isArray_) {
00813         delete ptr_;
00814       } else {
00815         delete[] ptr_;
00816       }
00817     }
00818   };
00819 
00820 } // namespace odbc
00821 
00822 
00823 #endif // __ODBCXX_TYPES_H

Go back to the freeodbc++ homepage