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 #if !defined(ODBCXX_QT)
00029 # include <string>
00030 # else
00031 # include <qstring.h>
00032 #endif
00033 #include <ctime>
00034 
00035 #if defined(ODBCXX_QT)
00036 class QIODevice;
00037 #endif
00038 
00039 #if defined(ODBCXX_HAVE_ISQL_H) && defined(ODBCXX_HAVE_ISQLEXT_H)
00040 # include <isql.h>
00041 # include <isqlext.h>
00042 #elif defined(ODBCXX_HAVE_SQL_H) && defined(ODBCXX_HAVE_SQLEXT_H)
00043 # include <sql.h>
00044 # include <sqlext.h>
00045 #else
00046 # error "Whoops. Can not recognize the ODBC subsystem."
00047 #endif
00048 
00049 // fixups for current iODBC, which kindly doesn't provide SQL_TRUE and
00050 // SQL_FALSE macros
00051 
00052 #if !defined(SQL_TRUE)
00053 # define SQL_TRUE 1
00054 #endif
00055 
00056 #if !defined(SQL_FALSE)
00057 # define SQL_FALSE 0
00058 #endif
00059 
00060 // MS ODBC SDK misses this in some releases
00061 #if ODBCVER >= 0x0300 && !defined(SQL_NOT_DEFERRABLE)
00062 # define SQL_NOT_DEFERRABLE 7
00063 #endif
00064 
00065 
00066 // Setup our ODBC3_C (odbc3 conditional) macro
00067 #if ODBCVER >= 0x0300
00068 
00069 # define ODBC3_C(odbc3_value,old_value) odbc3_value
00070 
00071 #else
00072 
00073 # define ODBC3_C(odbc3_value,old_value) old_value
00074 
00075 #endif
00076 
00077 
00078 // ODBC3_DC (odbc3 dynamic conditional)
00079 // Every context using this macro should provide
00080 // a this->_getDriverInfo() method returning
00081 // a const DriverInfo*
00082 
00083 #if ODBCVER >= 0x0300
00084 
00085 # define ODBC3_DC(odbc3_value,old_value) \
00086 (this->_getDriverInfo()->getMajorVersion()>=3?odbc3_value:old_value)
00087 
00088 #else
00089 
00090 # define ODBC3_DC(odbc3_value,old_value) old_value
00091 
00092 #endif
00093 
00094 #if defined(ODBCXX_HAVE_INTTYPES_H)
00095 # include <inttypes.h>
00096 #endif
00097 
00098 #include <vector>
00099 
00100 
00101 namespace odbc {
00102 
00103   // We want Long to be at least 64 bits
00104 
00105 #if defined(WIN32)
00106   
00107   typedef __int64 Long;
00108 
00109 #elif defined(ODBCXX_HAVE_INTTYPES_H)
00110 
00111   typedef int64_t Long;
00112 
00113 #else
00114 
00115 # if ODBCXX_SIZEOF_INT == 8
00116 
00117   typedef int Long;
00118 
00119 # elif ODBCXX_SIZEOF_LONG == 8
00120   
00121   typedef long Long;
00122 
00123 # elif ODBCXX_SIZEOF_LONG_LONG == 8
00124 
00125   typedef long long Long;
00126 
00127 # else
00128   
00129 #  error "Can't find an appropriate at-least-64-bit integer"
00130 
00131 # endif
00132 
00133 #endif
00134 
00135 
00136   //constants:
00137   //how much we try to fetch with each SQLGetData call
00138   const int GETDATA_CHUNK_SIZE=4*1024;
00139   //how much we write with each SQLPutData call
00140   const int PUTDATA_CHUNK_SIZE=GETDATA_CHUNK_SIZE;
00141 
00142   //how much we read/write in string<->stream conversion
00143   //better names for those?
00144   const int STRING_TO_STREAM_CHUNK_SIZE=1024;
00145   const int STREAM_TO_STRING_CHUNK_SIZE=STRING_TO_STREAM_CHUNK_SIZE;
00146 
00147 
00148 
00149 
00150 
00153   struct Types {
00156     enum SQLType {
00158       BIGINT            = SQL_BIGINT, 
00160       BINARY            = SQL_BINARY,
00162       BIT               = SQL_BIT,
00164       CHAR              = SQL_CHAR,
00166       DATE              = ODBC3_C(SQL_TYPE_DATE,SQL_DATE),
00168       DECIMAL           = SQL_DECIMAL,
00170       DOUBLE            = SQL_DOUBLE,
00172       FLOAT             = SQL_FLOAT,
00174       INTEGER           = SQL_INTEGER,
00176       LONGVARBINARY     = SQL_LONGVARBINARY,
00178       LONGVARCHAR       = SQL_LONGVARCHAR,
00180       NUMERIC           = SQL_NUMERIC,
00182       REAL              = SQL_REAL,
00184       SMALLINT          = SQL_SMALLINT,
00186       TIME              = ODBC3_C(SQL_TYPE_TIME,SQL_TIME),
00188       TIMESTAMP         = ODBC3_C(SQL_TYPE_TIMESTAMP,SQL_TIMESTAMP),
00190       TINYINT           = SQL_TINYINT,
00192       VARBINARY         = SQL_VARBINARY,
00194       VARCHAR           = SQL_VARCHAR
00195     };
00196   };
00197 
00198 
00199 #if !defined(ODBCXX_QT)
00206   class ODBCXX_EXPORT Bytes {
00207   private:
00208     struct Rep {
00209       signed char* buf_;
00210       size_t len_;
00211       int refCount_;
00212       Rep(const signed char* b, size_t l)
00213         :len_(l), refCount_(0) {
00214         if(len_>0) {
00215           buf_=new signed char[len_];
00216           memcpy((void*)buf_,(void*)b,len_);
00217         } else {
00218           buf_=NULL;
00219         }
00220       }
00221       ~Rep() {
00222         delete buf_;
00223       }
00224     };
00225 
00226     Rep* rep_;
00227   public:
00229     Bytes()
00230       :rep_(new Rep(NULL,0)) {
00231       rep_->refCount_++;
00232     }
00233 
00235     Bytes(const signed char* data, size_t dataLen)
00236       :rep_(new Rep(data,dataLen)) {
00237       rep_->refCount_++;
00238     }
00239 
00241     Bytes(const Bytes& b)
00242       :rep_(b.rep_) {
00243       rep_->refCount_++;
00244     }
00245 
00247     Bytes& operator=(const Bytes& b) {
00248       if(--rep_->refCount_==0) {
00249         delete rep_;
00250       }
00251       rep_=b.rep_;
00252       rep_->refCount_++;
00253       return *this;
00254     }
00255     
00257     ~Bytes() { 
00258       if(--rep_->refCount_==0) {
00259         delete rep_;
00260       }
00261     }
00262 
00264     const signed char* getData() const { 
00265       return rep_->buf_;
00266     }
00267 
00269     size_t getSize() const {
00270       return rep_->len_;
00271     }
00272   };
00273 #endif
00274 
00276   class ODBCXX_EXPORT Date {
00277   protected:
00278     int year_;
00279     int month_;
00280     int day_;
00281 
00282     virtual void _invalid(const char* what, int value);
00283 
00284     int _validateYear(int y) {
00285       return y;
00286     }
00287     
00288     int _validateMonth(int m) {
00289       if(m<1 || m>12) {
00290         this->_invalid("month",m);
00291       }
00292       return m;
00293     }
00294     
00295     int _validateDay(int d) {
00296       if(d<1 || d>31) {
00297         this->_invalid("day",d);
00298       }
00299       return d;
00300     }
00301 
00302   public:
00305     Date(int year, int month, int day) {
00306       this->setYear(year);
00307       this->setMonth(month);
00308       this->setDay(day);
00309     }
00310 
00315     explicit Date();
00316 
00321     Date(time_t t) {
00322       this->setTime(t);
00323     }
00324 
00329     Date(const ODBCXX_STRING& str) {
00330       this->parse(str);
00331     }
00332 
00334     Date(const Date& d)
00335       :year_(d.year_),
00336        month_(d.month_),
00337        day_(d.day_) {}
00338 
00340     Date& operator=(const Date& d) {
00341       year_=d.year_;
00342       month_=d.month_;
00343       day_=d.day_;
00344       return *this;
00345     }
00346 
00348     virtual ~Date() {}
00349 
00351     virtual void setTime(time_t t);
00352 
00354     time_t getTime() const;
00355 
00357     void parse(const ODBCXX_STRING& str);
00358 
00360     int getYear() const {
00361       return year_;
00362     }
00363 
00365     int getMonth() const {
00366       return month_;
00367     }
00368 
00370     int getDay() const {
00371       return day_;
00372     }
00373 
00375     void setYear(int year) {
00376       year_=this->_validateYear(year);
00377     }
00378 
00380     void setMonth(int month) {
00381       month_=this->_validateMonth(month);
00382     }
00383 
00385     void setDay(int day) {
00386       day_=this->_validateDay(day);
00387     }
00388 
00390     virtual ODBCXX_STRING toString() const;
00391   };
00392 
00394   class ODBCXX_EXPORT Time {
00395   protected:
00396     int hour_;
00397     int minute_;
00398     int second_;
00399 
00400     virtual void _invalid(const char* what, int value);
00401 
00402     int _validateHour(int h) {
00403       if(h<0 || h>23) {
00404         this->_invalid("hour",h);
00405       }
00406       return h;
00407     }
00408 
00409     int _validateMinute(int m) {
00410       if(m<0 || m>59) {
00411         this->_invalid("minute",m);
00412       }
00413       return m;
00414     }
00415 
00416     int _validateSecond(int s) {
00417       if(s<0 || s>61) {
00418         this->_invalid("second",s);
00419       }
00420       return s;
00421     }
00422 
00423   public:
00425     Time(int hour, int minute, int second) {
00426       this->setHour(hour);
00427       this->setMinute(minute);
00428       this->setSecond(second);
00429     }
00430 
00435     explicit Time();
00436 
00441     Time(time_t t) {
00442       this->setTime(t);
00443     }
00444 
00449     Time(const ODBCXX_STRING& str) {
00450       this->parse(str);
00451     }
00452 
00454     Time(const Time& t)
00455       :hour_(t.hour_),
00456        minute_(t.minute_),
00457        second_(t.second_) {}
00458 
00460     Time& operator=(const Time& t) {
00461       hour_=t.hour_;
00462       minute_=t.minute_;
00463       second_=t.second_;
00464       return *this;
00465     }
00466 
00468     virtual ~Time() {}
00469 
00471     virtual void setTime(time_t t);
00472 
00474     time_t getTime() const;
00475 
00477     void parse(const ODBCXX_STRING& str);
00478 
00480     int getHour() const {
00481       return hour_;
00482     }
00483 
00485     int getMinute() const {
00486       return minute_;
00487     }
00488 
00490     int getSecond() const {
00491       return second_;
00492     }
00493 
00495     void setHour(int h) {
00496       hour_=this->_validateHour(h);
00497     }
00498 
00500     void setMinute(int m) {
00501       minute_=this->_validateMinute(m);
00502     }
00503 
00505     void setSecond(int s) {
00506       second_=this->_validateSecond(s);
00507     }
00508 
00509     virtual ODBCXX_STRING toString() const;
00510   };
00511 
00512 
00515   class ODBCXX_EXPORT Timestamp : public Date, public Time {
00516   private:
00517     int nanos_;
00518     
00519     virtual void _invalid(const char* what, int value);
00520 
00521     int _validateNanos(int n) {
00522       if(n<0) {
00523         this->_invalid("nanoseconds",n);
00524       }
00525       return n;
00526     }
00527 
00528   public:
00530     Timestamp(int year, int month, int day,
00531               int hour, int minute, int second,
00532               int nanos =0)
00533       :Date(year,month,day), Time(hour,minute,second) {
00534       this->setNanos(nanos);
00535     }
00536 
00541     explicit Timestamp();
00542 
00547     Timestamp(time_t t) {
00548       this->setTime(t);
00549     }
00550 
00555     Timestamp(const ODBCXX_STRING& s) {
00556       this->parse(s);
00557     }
00558 
00559 
00561     Timestamp(const Timestamp& t)
00562       :Date(t),Time(t),nanos_(t.nanos_) {}
00563 
00565     Timestamp& operator=(const Timestamp& t) {
00566       Date::operator=(t);
00567       Time::operator=(t);
00568       nanos_=t.nanos_;
00569       return *this;
00570     }
00571 
00573     virtual ~Timestamp() {}
00574 
00576     virtual void setTime(time_t t);
00577     
00579     virtual time_t getTime() {
00580       return Date::getTime()+Time::getTime();
00581     }
00582 
00585     void parse(const ODBCXX_STRING& s);
00586 
00588     int getNanos() const {
00589       return nanos_;
00590     }
00591 
00593     void setNanos(int nanos) {
00594       nanos_=this->_validateNanos(nanos);
00595     }
00596 
00597     virtual ODBCXX_STRING toString() const;
00598   };
00599 
00600 
00601   //this is used for several 'lists of stuff' below
00602   //expects T to be a pointer-to-something, and
00603   //the contents will get deleted when the vector 
00604   //itself is deleted
00605   template <class T> class CleanVector : public std::vector<T> {
00606   private:
00607     CleanVector(const CleanVector<T>&); //forbid
00608     CleanVector<T>& operator=(const CleanVector<T>&); //forbid
00609 
00610   public:
00611     explicit CleanVector() {}
00612     virtual ~CleanVector() {
00613       typename std::vector<T>::iterator i=this->begin();
00614       typename std::vector<T>::iterator end=this->end();
00615       while(i!=end) {
00616         delete *i;
00617         ++i;
00618       }
00619       this->clear();
00620     }
00621   };
00622 
00623 
00626   class ODBCXX_EXPORT DriverMessage {
00627     friend class ErrorHandler;
00628 
00629   private:
00630     char state_[SQL_SQLSTATE_SIZE+1];
00631     char description_[SQL_MAX_MESSAGE_LENGTH];
00632     SQLINTEGER nativeCode_;
00633 
00634     DriverMessage() {}
00635 
00636   public:
00637     virtual ~DriverMessage() {}
00638 
00639     const char* getSQLState() const {
00640       return state_;
00641     }
00642 
00643     const char* getDescription() const {
00644       return description_;
00645     }
00646 
00647     int getNativeCode() const {
00648       return nativeCode_;
00649     }
00650   };
00651 
00652   
00655   class SQLException : public std::exception {
00656   private:
00657     ODBCXX_STRING reason_;
00658     ODBCXX_STRING sqlState_;
00659     int errorCode_;
00660 #if defined(ODBCXX_QT)
00661     QCString reason8_;
00662 #endif
00663     
00664   public:
00666     SQLException(const ODBCXX_STRING& reason ="", 
00667                  const ODBCXX_STRING& sqlState ="",
00668                  int vendorCode =0)
00669       :reason_(reason), 
00670        sqlState_(sqlState),
00671        errorCode_(vendorCode) 
00672 #if defined(ODBCXX_QT)
00673       ,reason8_(reason.local8Bit())
00674 #endif
00675 {}
00676 
00678     SQLException(const DriverMessage& dm)
00679       :reason_(dm.getDescription()),
00680        sqlState_(dm.getSQLState()),
00681        errorCode_(dm.getNativeCode()) {}
00682 
00684     virtual ~SQLException() throw() {}
00685 
00687     int getErrorCode() const {
00688       return errorCode_;
00689     }
00690     
00695     const ODBCXX_STRING& getSQLState() const {
00696       return sqlState_;
00697     }
00698     
00700     const ODBCXX_STRING& getMessage() const {
00701       return reason_;
00702     }
00703 
00704 
00706     virtual const char* what() const throw() {
00707       // the conversion from QString involves a temporary, which
00708       // doesn't survive this scope. So here, we do a conditional
00709 #if defined(ODBCXX_QT)
00710       return reason8_.data();
00711 #else
00712       return reason_.c_str();
00713 #endif
00714     }
00715   };
00716 
00717 
00722   class SQLWarning : public SQLException {
00723 
00724     SQLWarning(const SQLWarning&); //forbid
00725     SQLWarning& operator=(const SQLWarning&); //forbid
00726 
00727   public:
00729     SQLWarning(const ODBCXX_STRING& reason ="",
00730                const ODBCXX_STRING& sqlState ="",
00731                int vendorCode =0)
00732       :SQLException(reason,sqlState,vendorCode) {}
00733     
00735     SQLWarning(const DriverMessage& dm)
00736       :SQLException(dm) {}
00737     
00739     virtual ~SQLWarning() throw() {}
00740   };
00741 
00742   typedef CleanVector<SQLWarning*> WarningList;
00743   
00744 
00745   template <class T> class Deleter {
00746   private:
00747     T* ptr_;
00748     bool isArray_;
00749 
00750     Deleter(const Deleter<T>&);
00751     Deleter<T>& operator=(const Deleter<T>&);
00752 
00753   public:
00754     explicit Deleter(T* ptr, bool isArray =false) 
00755       :ptr_(ptr), isArray_(isArray) {}
00756     ~Deleter() {
00757       if(!isArray_) {
00758         delete ptr_;
00759       } else {
00760         delete[] ptr_;
00761       }
00762     }
00763   };
00764 
00765 }; // namespace odbc
00766 
00767 
00768 #endif // __ODBCXX_TYPES_H

Go back to the freeodbc++ homepage