Main Page   Namespace List   Class Hierarchy   Compound List   Header Files   Namespace Members   Compound Members  

odbc++/types.h

This is the verbatim text of the types.h include file.
/* 
   This file is part of libodbc++.
   
   Copyright (C) 1999-2000 Manush Dodunekov <manush@stendahls.net>
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.
   
   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#ifndef __ODBCXX_TYPES_H
#define __ODBCXX_TYPES_H

#include <odbc++/setup.h>

#include <exception>
#if !defined(ODBCXX_QT)
# include <string>
# else
# include <qstring.h>
#endif
#include <ctime>

#if defined(ODBCXX_QT)
class QIODevice;
#endif

#if defined(ODBCXX_HAVE_ISQL_H) && defined(ODBCXX_HAVE_ISQLEXT_H)
# include <isql.h>
# include <isqlext.h>
#elif defined(ODBCXX_HAVE_SQL_H) && defined(ODBCXX_HAVE_SQLEXT_H)
# include <sql.h>
# include <sqlext.h>
#else
# error "Whoops. Can not recognize the ODBC subsystem."
#endif

// fixups for current iODBC, which kindly doesn't provide SQL_TRUE and
// SQL_FALSE macros

#if !defined(SQL_TRUE)
# define SQL_TRUE 1
#endif

#if !defined(SQL_FALSE)
# define SQL_FALSE 0
#endif

// MS ODBC SDK misses this in some releases
#if ODBCVER >= 0x0300 && !defined(SQL_NOT_DEFERRABLE)
# define SQL_NOT_DEFERRABLE 7
#endif


// Setup our ODBC3_C (odbc3 conditional) macro
#if ODBCVER >= 0x0300

# define ODBC3_C(odbc3_value,old_value) odbc3_value

#else

# define ODBC3_C(odbc3_value,old_value) old_value

#endif


// ODBC3_DC (odbc3 dynamic conditional)
// Every context using this macro should provide
// a this->_getDriverInfo() method returning
// a const DriverInfo*

#if ODBCVER >= 0x0300

# define ODBC3_DC(odbc3_value,old_value) \
(this->_getDriverInfo()->getMajorVersion()>=3?odbc3_value:old_value)

#else

# define ODBC3_DC(odbc3_value,old_value) old_value

#endif

#if defined(ODBCXX_HAVE_INTTYPES_H)
# include <inttypes.h>
#endif

#include <vector>


namespace odbc {

  // We want Long to be at least 64 bits

#if defined(WIN32)
  
  typedef __int64 Long;

#elif defined(ODBCXX_HAVE_INTTYPES_H)

  typedef int64_t Long;

#else

# if ODBCXX_SIZEOF_INT == 8

  typedef int Long;

# elif ODBCXX_SIZEOF_LONG == 8
  
  typedef long Long;

# elif ODBCXX_SIZEOF_LONG_LONG == 8

  typedef long long Long;

# else
  
#  error "Can't find an appropriate at-least-64-bit integer"

# endif

#endif


  //constants:
  //how much we try to fetch with each SQLGetData call
  const int GETDATA_CHUNK_SIZE=4*1024;
  //how much we write with each SQLPutData call
  const int PUTDATA_CHUNK_SIZE=GETDATA_CHUNK_SIZE;

  //how much we read/write in string<->stream conversion
  //better names for those?
  const int STRING_TO_STREAM_CHUNK_SIZE=1024;
  const int STREAM_TO_STRING_CHUNK_SIZE=STRING_TO_STREAM_CHUNK_SIZE;





  struct Types {
    enum SQLType {
      BIGINT            = SQL_BIGINT, 
      BINARY            = SQL_BINARY,
      BIT               = SQL_BIT,
      CHAR              = SQL_CHAR,
      DATE              = ODBC3_C(SQL_TYPE_DATE,SQL_DATE),
      DECIMAL           = SQL_DECIMAL,
      DOUBLE            = SQL_DOUBLE,
      FLOAT             = SQL_FLOAT,
      INTEGER           = SQL_INTEGER,
      LONGVARBINARY     = SQL_LONGVARBINARY,
      LONGVARCHAR       = SQL_LONGVARCHAR,
      NUMERIC           = SQL_NUMERIC,
      REAL              = SQL_REAL,
      SMALLINT          = SQL_SMALLINT,
      TIME              = ODBC3_C(SQL_TYPE_TIME,SQL_TIME),
      TIMESTAMP         = ODBC3_C(SQL_TYPE_TIMESTAMP,SQL_TIMESTAMP),
      TINYINT           = SQL_TINYINT,
      VARBINARY         = SQL_VARBINARY,
      VARCHAR           = SQL_VARCHAR
    };
  };


#if !defined(ODBCXX_QT)
  class ODBCXX_EXPORT Bytes {
  private:
    struct Rep {
      signed char* buf_;
      size_t len_;
      int refCount_;
      Rep(const signed char* b, size_t l)
        :len_(l), refCount_(0) {
        if(len_>0) {
          buf_=new signed char[len_];
          memcpy((void*)buf_,(void*)b,len_);
        } else {
          buf_=NULL;
        }
      }
      ~Rep() {
        delete buf_;
      }
    };

    Rep* rep_;
  public:
    Bytes()
      :rep_(new Rep(NULL,0)) {
      rep_->refCount_++;
    }

    Bytes(const signed char* data, size_t dataLen)
      :rep_(new Rep(data,dataLen)) {
      rep_->refCount_++;
    }

    Bytes(const Bytes& b)
      :rep_(b.rep_) {
      rep_->refCount_++;
    }

    Bytes& operator=(const Bytes& b) {
      if(--rep_->refCount_==0) {
        delete rep_;
      }
      rep_=b.rep_;
      rep_->refCount_++;
      return *this;
    }
    
    ~Bytes() { 
      if(--rep_->refCount_==0) {
        delete rep_;
      }
    }

    const signed char* getData() const { 
      return rep_->buf_;
    }

    size_t getSize() const {
      return rep_->len_;
    }
  };
#endif

  class ODBCXX_EXPORT Date {
  protected:
    int year_;
    int month_;
    int day_;

    virtual void _invalid(const char* what, int value);

    int _validateYear(int y) {
      return y;
    }
    
    int _validateMonth(int m) {
      if(m<1 || m>12) {
        this->_invalid("month",m);
      }
      return m;
    }
    
    int _validateDay(int d) {
      if(d<1 || d>31) {
        this->_invalid("day",d);
      }
      return d;
    }

  public:
    Date(int year, int month, int day) {
      this->setYear(year);
      this->setMonth(month);
      this->setDay(day);
    }

    explicit Date();

    Date(time_t t) {
      this->setTime(t);
    }

    Date(const ODBCXX_STRING& str) {
      this->parse(str);
    }

    Date(const Date& d)
      :year_(d.year_),
       month_(d.month_),
       day_(d.day_) {}

    Date& operator=(const Date& d) {
      year_=d.year_;
      month_=d.month_;
      day_=d.day_;
      return *this;
    }

    virtual ~Date() {}

    virtual void setTime(time_t t);

    time_t getTime() const;

    void parse(const ODBCXX_STRING& str);

    int getYear() const {
      return year_;
    }

    int getMonth() const {
      return month_;
    }

    int getDay() const {
      return day_;
    }

    void setYear(int year) {
      year_=this->_validateYear(year);
    }

    void setMonth(int month) {
      month_=this->_validateMonth(month);
    }

    void setDay(int day) {
      day_=this->_validateDay(day);
    }

    virtual ODBCXX_STRING toString() const;
  };

  class ODBCXX_EXPORT Time {
  protected:
    int hour_;
    int minute_;
    int second_;

    virtual void _invalid(const char* what, int value);

    int _validateHour(int h) {
      if(h<0 || h>23) {
        this->_invalid("hour",h);
      }
      return h;
    }

    int _validateMinute(int m) {
      if(m<0 || m>59) {
        this->_invalid("minute",m);
      }
      return m;
    }

    int _validateSecond(int s) {
      if(s<0 || s>61) {
        this->_invalid("second",s);
      }
      return s;
    }

  public:
    Time(int hour, int minute, int second) {
      this->setHour(hour);
      this->setMinute(minute);
      this->setSecond(second);
    }

    explicit Time();

    Time(time_t t) {
      this->setTime(t);
    }

    Time(const ODBCXX_STRING& str) {
      this->parse(str);
    }

    Time(const Time& t)
      :hour_(t.hour_),
       minute_(t.minute_),
       second_(t.second_) {}

    Time& operator=(const Time& t) {
      hour_=t.hour_;
      minute_=t.minute_;
      second_=t.second_;
      return *this;
    }

    virtual ~Time() {}

    virtual void setTime(time_t t);

    time_t getTime() const;

    void parse(const ODBCXX_STRING& str);

    int getHour() const {
      return hour_;
    }

    int getMinute() const {
      return minute_;
    }

    int getSecond() const {
      return second_;
    }

    void setHour(int h) {
      hour_=this->_validateHour(h);
    }

    void setMinute(int m) {
      minute_=this->_validateMinute(m);
    }

    void setSecond(int s) {
      second_=this->_validateSecond(s);
    }

    virtual ODBCXX_STRING toString() const;
  };


  class ODBCXX_EXPORT Timestamp : public Date, public Time {
  private:
    int nanos_;
    
    virtual void _invalid(const char* what, int value);

    int _validateNanos(int n) {
      if(n<0) {
        this->_invalid("nanoseconds",n);
      }
      return n;
    }

  public:
    Timestamp(int year, int month, int day,
              int hour, int minute, int second,
              int nanos =0)
      :Date(year,month,day), Time(hour,minute,second) {
      this->setNanos(nanos);
    }

    explicit Timestamp();

    Timestamp(time_t t) {
      this->setTime(t);
    }

    Timestamp(const ODBCXX_STRING& s) {
      this->parse(s);
    }


    Timestamp(const Timestamp& t)
      :Date(t),Time(t),nanos_(t.nanos_) {}

    Timestamp& operator=(const Timestamp& t) {
      Date::operator=(t);
      Time::operator=(t);
      nanos_=t.nanos_;
      return *this;
    }

    virtual ~Timestamp() {}

    virtual void setTime(time_t t);
    
    virtual time_t getTime() {
      return Date::getTime()+Time::getTime();
    }

    void parse(const ODBCXX_STRING& s);

    int getNanos() const {
      return nanos_;
    }

    void setNanos(int nanos) {
      nanos_=this->_validateNanos(nanos);
    }

    virtual ODBCXX_STRING toString() const;
  };


  //this is used for several 'lists of stuff' below
  //expects T to be a pointer-to-something, and
  //the contents will get deleted when the vector 
  //itself is deleted
  template <class T> class CleanVector : public std::vector<T> {
  private:
    CleanVector(const CleanVector<T>&); //forbid
    CleanVector<T>& operator=(const CleanVector<T>&); //forbid

  public:
    explicit CleanVector() {}
    virtual ~CleanVector() {
      typename std::vector<T>::iterator i=this->begin();
      typename std::vector<T>::iterator end=this->end();
      while(i!=end) {
        delete *i;
        ++i;
      }
      this->clear();
    }
  };


  class ODBCXX_EXPORT DriverMessage {
    friend class ErrorHandler;

  private:
    char state_[SQL_SQLSTATE_SIZE+1];
    char description_[SQL_MAX_MESSAGE_LENGTH];
    SQLINTEGER nativeCode_;

    DriverMessage() {}

  public:
    virtual ~DriverMessage() {}

    const char* getSQLState() const {
      return state_;
    }

    const char* getDescription() const {
      return description_;
    }

    int getNativeCode() const {
      return nativeCode_;
    }
  };

  
  class SQLException : public std::exception {
  private:
    ODBCXX_STRING reason_;
    ODBCXX_STRING sqlState_;
    int errorCode_;
#if defined(ODBCXX_QT)
    QCString reason8_;
#endif
    
  public:
    SQLException(const ODBCXX_STRING& reason ="", 
                 const ODBCXX_STRING& sqlState ="",
                 int vendorCode =0)
      :reason_(reason), 
       sqlState_(sqlState),
       errorCode_(vendorCode) 
#if defined(ODBCXX_QT)
      ,reason8_(reason.local8Bit())
#endif
{}

    SQLException(const DriverMessage& dm)
      :reason_(dm.getDescription()),
       sqlState_(dm.getSQLState()),
       errorCode_(dm.getNativeCode()) {}

    virtual ~SQLException() {}

    int getErrorCode() const {
      return errorCode_;
    }
    
    const ODBCXX_STRING& getSQLState() const {
      return sqlState_;
    }
    
    const ODBCXX_STRING& getMessage() const {
      return reason_;
    }


    virtual const char* what() const {
      // the conversion from QString involves a temporary, which
      // doesn't survive this scope. So here, we do a conditional
#if defined(ODBCXX_QT)
      return reason8_.data();
#else
      return reason_.c_str();
#endif
    }
  };


  class SQLWarning : public SQLException {

    SQLWarning(const SQLWarning&); //forbid
    SQLWarning& operator=(const SQLWarning&); //forbid

  public:
    SQLWarning(const ODBCXX_STRING& reason ="",
               const ODBCXX_STRING& sqlState ="",
               int vendorCode =0)
      :SQLException(reason,sqlState,vendorCode) {}
    
    SQLWarning(const DriverMessage& dm)
      :SQLException(dm) {}
    
    virtual ~SQLWarning() {}
  };

  typedef CleanVector<SQLWarning*> WarningList;
  

  template <class T> class Deleter {
  private:
    T* ptr_;
    bool isArray_;

    Deleter(const Deleter<T>&);
    Deleter<T>& operator=(const Deleter<T>&);

  public:
    explicit Deleter(T* ptr, bool isArray =false) 
      :ptr_(ptr), isArray_(isArray) {}
    ~Deleter() {
      if(!isArray_) {
        delete ptr_;
      } else {
        delete[] ptr_;
      }
    }
  };

}; // namespace odbc


#endif // __ODBCXX_TYPES_H

Go back to the freeodbc++ homepage