src/QOpenOCCI.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2008 Andrew White. All rights reserved.
00004 **
00005 ** This file is part of the QOpenOCCI library.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the 
00010 ** packaging of this file.
00011 **
00012 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014 **
00015 ****************************************************************************/
00016 
00017 
00018 #ifndef QOPENOCCI_H
00019 #define QOPENOCCI_H
00020 
00021 #include <QtSql/QtSql>
00022 
00023 #include <iostream>
00024 #include <memory>
00025 #include "ocilib/ocilib.h"
00026 
00031 using namespace std;
00032 
00033 //Default amount of memory/rows to use for prefetching ... 1Mb/100rows
00034 #define DEFAULT_MEMORY_PREFETCH 1048576
00035 #define DEFAULT_ROWS_PREFETCH   100
00036 
00037 class QOpenOCCIResult;
00038 class QOpenOCCIDriver;
00039 
00040 #define QOPEN_OCCI_EXCEPTION(str) (QOpenOCCIException("Error %s[%d]: %s", __FILE__, __LINE__, str))
00041 #define MAX_ERROR_LEN 1024
00042 
00043 class QOpenOCCIException : public std::exception {
00044 public:
00045     QOpenOCCIException(char * format, ...) : std::exception() {
00046         va_list args;
00047         va_start(args, format);
00048         vsnprintf(error_msg, MAX_ERROR_LEN, format, args);
00049         va_end(args);
00050     }
00051 
00052     virtual const char * what() const throw() {return error_msg;}
00053     virtual ~QOpenOCCIException() throw() {};
00054 private:
00055     char error_msg[MAX_ERROR_LEN];
00056 };
00057 
00058 //May need to just get rid of this class and use a vector inside of the Result Class...
00059 class QOpenOCCICache
00060 {
00061 public:
00062     QOpenOCCICache(){};
00063     
00064     bool isRowCached(int row_id) { return row_id < mCache.size(); }
00065     void clear() { mCache.clear(); }
00066     
00067     unsigned int size() { return mCache.size(); }
00068     
00069     QVector<QVariant>&  getLastRow() { return mCache.back(); }
00070     QVector<QVariant>&  getRow(unsigned int row_id) { return mCache[row_id]; }
00071     QVector<QVariant>&  addRow() { 
00072         mCache.append(QVector<QVariant>()); 
00073         return mCache.back();
00074     }
00075     
00076 private:
00077     QVector< QVector< QVariant > > mCache;
00078 };
00079 
00080 class QOpenOCCIBindElement {
00081 public:
00082     virtual void free() = 0;
00083     virtual void* ptrValue() = 0;
00084     virtual QVariant toQVariant() const = 0;
00085     virtual ~QOpenOCCIBindElement() {};
00086     
00087     static char* QStringToChar(const QString& str) {
00088         int size = (str.isNull()) ? 4000
00089                                   : str.size()+1;
00090         char * ret = new char[size];
00091         memcpy(ret, str.toAscii().constData(), str.size()+1);
00092         return ret;
00093     }
00094     static OCI_Date* QDateToOCIDate( OCI_Connection* c, const QDate& date ){
00095         OCI_Date* ret = OCI_DateCreate(c);
00096         OCI_DateSetDate(ret, date.year(), date.month(), date.day());
00097         return ret;
00098     } 
00099     
00100     static OCI_Date* QDateToOCIDateTime( OCI_Connection* c, const QDateTime& date ){
00101         OCI_Date* ret = OCI_DateCreate(c);
00102         OCI_DateSetDate(ret, date.date().year(), date.date().month(), date.date().day());
00103         OCI_DateSetTime(ret, date.time().hour(), date.time().minute(), date.time().second());
00104         return ret;
00105     }
00106     
00107     static OCI_Date* QDateToOCITime( OCI_Connection* c, const QTime& time ){
00108         OCI_Date* ret = OCI_DateCreate(c);
00109         OCI_DateSetTime(ret, time.hour(), time.minute(), time.second());
00110         return ret;
00111     }
00112     
00113     static OCI_Lob* QByteArrayToBLOB( OCI_Connection* c, const QByteArray& buf ) {
00114         OCI_Lob* ret = OCI_LobCreate(c, OCI_BLOB);
00115         OCI_LobWrite(ret, (void*)buf.data(), buf.size());
00116         return ret;
00117     }
00118 };
00119 
00120 template <class C>
00121 class QOpenOCCIBindElementI : public QOpenOCCIBindElement{
00122 public:
00123     QOpenOCCIBindElementI(C* data);
00124     ~QOpenOCCIBindElementI();
00125 
00126     void free();
00127     void* ptrValue();
00128     QVariant toQVariant() const;
00129 
00130 private:
00131     C* mData;
00132 };
00133 
00134 class QOpenOCCIBindData {
00135 public:
00136     void add(const QString& key, QOpenOCCIBindElement* val) {
00137         if (mMap.contains(key)) mMap[key]->free();
00138         mMap[key] = val;
00139     }
00140     
00141     void cleanup() {
00142         QMapIterator<QString, QOpenOCCIBindElement*> i(mMap);
00143         while (i.hasNext()) {
00144             i.next();
00145             i.value()->free();
00146             delete i.value();
00147         }
00148         mMap.clear();
00149     }
00150     
00151     QOpenOCCIBindElement* operator[](const QString& key) { return mMap[key]; }
00152 private:
00153     QMap<QString, QOpenOCCIBindElement*> mMap;
00154 };
00155 
00156 
00157 
00158 class QOpenOCCIMetadata {
00159 public:
00160     QOpenOCCIMetadata(){};
00161     QOpenOCCIMetadata(OCI_Resultset* resultSet);
00162      
00163     struct ColumnMetadata { 
00164         QString name;
00165         QString type;
00166         int typeCode;
00167         int size;
00168         int precision;
00169         int scale;
00170         bool nullable;
00171     };
00172         
00173     QVector< ColumnMetadata > mColMetadata;
00174 };
00175 
00176 class QOpenOCCIResult : public QSqlResult
00177 {
00178 public:
00179     QOpenOCCIResult(
00180         const QSqlDriver* d               = NULL,
00181         OCI_Connection*   c               = NULL, 
00182         unsigned int      prefetch_memory = DEFAULT_MEMORY_PREFETCH, 
00183         unsigned int      prefetch_rows   = DEFAULT_ROWS_PREFETCH
00184     );
00185     
00186     ~QOpenOCCIResult();
00187     
00188 protected:
00189     QVariant    data( int );
00190     bool        exec();
00191     bool        isNull( int );
00192     bool        reset ( const QString& );
00193     bool        fetch( int );
00194     bool        fetchFirst();   //boundValue issue
00195     bool        fetchNext();
00196     bool        fetchPrevious();
00197     bool        fetchLast();
00198     QSqlRecord  record() const;
00199     int         size()  { return -1; }
00200     int         numRowsAffected();
00201     bool        prepare ( const QString & query );
00202     bool        savePrepare ( const QString & query );
00203     void        setQuery ( const QString & query );
00204     
00205     static const char* EXEC_FAILED;
00206     static const char* BIND_FAILED;
00207 private:
00208     void addRowToCache();
00209     void bind(QString name, const QVariant& val, QSql::ParamType paramType);
00210     void updateBoundResults();
00211     void cleanup();
00212     void rebind(int bound_index, const QVariant & val, QSql::ParamType paramType);
00213     
00214     static QVariant::Type ocilib_to_qvariant_type(int occi_type);
00215     
00216     OCI_Connection * mConnection;  
00217     OCI_Statement  * mStatement;   
00218     OCI_Resultset  * mResultSet;   
00219     
00220     QOpenOCCIMetadata           mResultMetadata;
00221     QOpenOCCIBindData           mBindData;
00222     //vector<MetaData>          mResultMetadata; ///< Oracle's column metadata
00223     map<QString, int>           mBindNameIndex;  
00224     //QMap<int, QByteArray>     mBindLobs;       ///< ByteArrays to use for lob streams
00225     QOpenOCCICache              mCache;          
00226 
00227 };
00228 
00230 class QOpenOCCIDriver : public QSqlDriver
00231 {
00232 public:
00234     QOpenOCCIDriver();
00236     ~QOpenOCCIDriver();
00237     
00242     bool    hasFeature( DriverFeature ) const;
00243     
00257     bool    open( const QString& db, 
00258                   const QString& user, 
00259                   const QString& password, 
00260                   const QString& host, 
00261                   int            port    = 1521, 
00262                   const QString& options = "");
00263     void    close() {}
00264     QSqlQuery   createQuery() const;
00265     QSqlResult* createResult() const;
00266     
00267     bool beginTransaction ();
00268     bool commitTransaction ();
00269     bool rollbackTransaction();
00270     
00271     static const char* CONNECTION_FAILED;
00272     static const char* CONNECTION_ALREADY_OPEN;
00273     static const char* COMMIT_FAILED;
00274     static const char* ROLLBACK_FAILED;
00275     static const char* PREFETCH_MEM_KEY;
00276     static const char* PREFETCH_ROWS_KEY;
00277     static const char* RESULT_FAILED;
00278 private:
00279     static void ErrHandle(OCI_Error *err);
00280     void closeConnection();
00281     
00282     static int    driverCount;
00283     //Environment * mEnv;         ///< Oracle Environment object
00284     OCI_Connection * mConnection;  
00285     
00286     QMap<QString, QString>    mOptionMap; 
00287 };
00288 #endif

Generated on Tue Mar 18 22:47:08 2008 for QOpenOCCI by  doxygen 1.5.3