TnFXSQLDB.h

Go to the documentation of this file.
00001 /********************************************************************************
00002 *                                                                               *
00003 *                              SQL Database Support                             *
00004 *                                                                               *
00005 *********************************************************************************
00006 * Copyright (C) 2005-2006 by Niall Douglas.   All Rights Reserved.              *
00007 *       NOTE THAT I DO NOT PERMIT ANY OF MY CODE TO BE PROMOTED TO THE GPL      *
00008 *********************************************************************************
00009 * This code is free software; you can redistribute it and/or modify it under    *
00010 * the terms of the GNU Library General Public License v2.1 as published by the  *
00011 * Free Software Foundation EXCEPT that clause 3 does not apply ie; you may not  *
00012 * "upgrade" this code to the GPL without my prior written permission.           *
00013 * Please consult the file "License_Addendum2.txt" accompanying this file.       *
00014 *                                                                               *
00015 * This code is distributed in the hope that it will be useful,                  *
00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                          *
00018 *********************************************************************************
00019 * $Id:                                                                          *
00020 ********************************************************************************/
00021 #if FX_SQLMODULE
00022 
00023 #ifndef TNFXSQLDB_H
00024 #define TNFXSQLDB_H
00025 
00026 #include "FXTime.h"
00027 #include "FXRefedObject.h"
00028 #include "QBuffer.h"
00029 #include "QHostAddress.h"
00030 #include "QTrans.h"
00031 #include <qcstring.h>
00032 
00033 #if FX_SQLMODULE==1
00034  #define FXSQLMODULEAPI FXAPI
00035 #elif FX_SQLMODULE==2
00036  #ifdef FOXDLL
00037   #ifdef FX_SQLMODULE_EXPORTS
00038    #define FXSQLMODULEAPI FXEXPORT
00039   #else
00040    #define FXSQLMODULEAPI FXIMPORT
00041   #endif
00042  #else
00043   #define FXSQLMODULEAPI
00044  #endif
00045 #endif
00046 
00047 namespace FX {
00048 
00129 #ifdef _MSC_VER
00130 #pragma warning(push)
00131 #pragma warning(disable: 4251) // class 1 needs to have dll-interface to be used by clients of class 2
00132 #pragma warning(disable: 4244) // Conversion from bigger to smaller, possible loss of data
00133 #pragma warning(disable: 4275) // non DLL-interface used as base for DLL-interface class
00134 #endif
00135 
00136 class QStringList;
00137 
00138 namespace TnFXSQLDBImpl
00139 {   // We can't partially specialise member functions (which is stupid of the C++ spec)
00140     template<bool isUnsignedInt, typename type, typename signedIntEquiv> struct checkForOverflow
00141     {
00142         static bool Do(const type *v) throw()
00143         {
00144             return false;
00145         }
00146     };
00147     template<typename type, typename signedIntEquiv> struct checkForOverflow<true, type, signedIntEquiv>
00148     {   // Called when type is an unsigned int
00149         static bool Do(const type *v) throw()
00150         {
00151             if(v && *v>Generic::BiggestValue<signedIntEquiv>::value)
00152             {   // Unsigned is overflowing its container so bump it
00153                 return true;
00154             }
00155             return false;
00156         }
00157     };
00158     template<> struct checkForOverflow<true, FXulong, FXlong>
00159     {   // Called when type is as big as it can be
00160         static bool Do(const FXulong *v) throw()
00161         {
00162             if(v && *v>(FXulong) Generic::BiggestValue<FXlong>::value)
00163             {   // Best we can do is print a message
00164 #ifdef DEBUG
00165                 fxmessage("WARNING: Unsigned 64 bit value overflows signed 64 bit database type!\n");
00166 #endif
00167             }
00168             return false;
00169         }
00170     };
00171     template<bool unknownType, typename type> struct DoSerialise;
00172     template<int sql92type, bool isUnsignedInt, typename type> struct BindImpl;
00173 }
00174 
00175 class TnFXSQLDBStatement;
00177 typedef FXRefingObject<TnFXSQLDBStatement> TnFXSQLDBStatementRef;
00178 class TnFXSQLDBCursor;
00180 typedef FXRefingObject<TnFXSQLDBCursor> TnFXSQLDBCursorRef;
00181 class TnFXSQLDBColumn;
00183 typedef FXRefingObject<TnFXSQLDBColumn> TnFXSQLDBColumnRef;
00184 
00185 
00239 struct TnFXSQLDBPrivate;
00240 class FXSQLMODULEAPI TnFXSQLDB
00241 {
00242     TnFXSQLDBPrivate *p;
00243     TnFXSQLDB(const TnFXSQLDB &);
00244     TnFXSQLDB &operator=(const TnFXSQLDB &);
00245 public:
00247     struct Capabilities
00248     {
00249         FXuint Transactions : 1;        
00250         FXuint QueryRows : 1;           
00251         FXuint NoTypeConstraints : 1;   
00252         FXuint HasBackwardsCursor : 1;  
00253         FXuint HasSettableCursor : 1;   
00254         FXuint HasStaticCursor : 1;     
00255         FXuint Asynchronous : 1;        
00256         Capabilities() { *((FXuint *) this)=0; }
00258         Capabilities &setTransactions(bool v=true) { Transactions=v; return *this; }
00260         Capabilities &setQueryRows(bool v=true) { QueryRows=v; return *this; }
00262         Capabilities &setNoTypeConstraints(bool v=true) { NoTypeConstraints=v; return *this; }
00264         Capabilities &setHasBackwardsCursor(bool v=true) { HasBackwardsCursor=v; return *this; }
00266         Capabilities &setHasSettableCursor(bool v=true) { HasSettableCursor=v; return *this; }
00268         Capabilities &setHasStaticCursor(bool v=true) { HasStaticCursor=v; return *this; }
00270         Capabilities &setAsynchronous(bool v=true) { Asynchronous=v; return *this; }
00271     };
00272 protected:
00273     TnFXSQLDB(Capabilities caps, const FXString &driverName, const FXString &dbname=FXString::nullStr(), const FXString &user=FXString::nullStr(), const QHostAddress &host=QHOSTADDRESS_LOCALHOST, FXushort port=0);
00274 public:
00275     virtual ~TnFXSQLDB();
00276 
00278     enum SQLDataType
00279     {
00280         Null=0,     
00281 
00282         VarChar,    
00283         Char,       
00284         WVarChar,   
00285         WChar,      
00286 
00287         TinyInt,    
00288         SmallInt,   
00289         Integer,    
00290         BigInt,     
00291         Decimal,    
00292         Numeric,    
00293 
00294         Real,       
00295         Double,     
00296         Float,      
00297 
00298         Timestamp,  
00299         Date,       
00300         Time,       
00301 
00302         BLOB,       
00303 
00304         LastSQLDataTypeEntry
00305     };
00307     static const char *sql92TypeAsString(SQLDataType type);
00308     typedef Generic::TL::create<void,
00309         FXString, FXString, FXString, FXString,
00310         FXchar, FXshort, FXint, FXlong,
00311         FXlong, FXlong
00312     >::value CPPDataTypes1;
00313     typedef Generic::TL::create<
00314         FXfloat, FXdouble,
00315         FXdouble,
00316         FXTime, FXTime, FXTime,
00317         QByteArray
00318     >::value CPPDataTypes2;
00320     typedef Generic::TL::append<CPPDataTypes1, CPPDataTypes2>::value CPPDataTypes;
00323     template<typename type> struct CPPToSQL92Type
00324     {   // Replace unsigned integrals with their signed equivalents
00325         static const int unsignedIntIdx=Generic::TL::find<Generic::IntegralLists::unsignedInts, type>::value;
00326         typedef typename Generic::TL::at<Generic::IntegralLists::signedInts, unsignedIntIdx>::value signedIntEquiv;
00327         typedef typename Generic::select<-1==unsignedIntIdx, type, signedIntEquiv>::value typeToUse;
00328 
00329         static const int directidx=Generic::TL::find<CPPDataTypes, typeToUse>::value;
00330         static const SQLDataType value=(SQLDataType)((-1==directidx) ? Generic::TL::findParent<CPPDataTypes, typeToUse>::value : directidx);
00331     };
00336     template<typename type> static SQLDataType toSQL92Type(const type *v=0)
00337     {
00338         FXSTATIC_ASSERT(LastSQLDataTypeEntry==Generic::TL::length<CPPDataTypes>::value, Mismatched_SQLDataTypes_And_CPPDataTypes);
00339         typedef CPPToSQL92Type<type> sql92type;
00340 
00341         return (SQLDataType)(sql92type::value+TnFXSQLDBImpl::checkForOverflow<-1!=sql92type::unsignedIntIdx, type, typename sql92type::signedIntEquiv>::Do(v));
00342     }
00344     template<template<typename type> class instance> struct toCPPType
00345         : Generic::TL::dynamicAt<CPPDataTypes1, instance>, Generic::TL::dynamicAt<CPPDataTypes2, instance>
00346     {
00347         typedef Generic::TL::dynamicAt<CPPDataTypes1, instance> Base1;
00348         typedef Generic::TL::dynamicAt<CPPDataTypes2, instance> Base2;
00350         toCPPType(SQLDataType datatype)
00351             : Base1(datatype<Generic::TL::length<CPPDataTypes1>::value ? datatype : Base1::DisableMagicIdx),
00352              Base2(datatype>=Generic::TL::length<CPPDataTypes1>::value ? datatype-Generic::TL::length<CPPDataTypes1>::value : Base1::DisableMagicIdx) { }
00354         template<typename P1, typename P2, typename P3, typename P4> toCPPType(SQLDataType datatype, P1 p1, P2 p2, P3 p3, P4 p4)
00355             : Base1(datatype<Generic::TL::length<CPPDataTypes1>::value ? datatype : Base1::DisableMagicIdx, p1, p2, p3, p4),
00356              Base2(datatype>=Generic::TL::length<CPPDataTypes1>::value ? datatype-Generic::TL::length<CPPDataTypes1>::value : Base1::DisableMagicIdx, p1, p2, p3, p4) { }
00357     };
00358 
00360     const FXString &driverName() const throw();
00362     Capabilities capabilities() const throw();
00364     virtual const FXString &versionInfo() const=0;
00366     const FXString &dbName() const throw();
00368     void setDBName(const FXString &dbname);
00370     const FXString &user() const throw();
00372     void setUser(const FXString &user);
00374     const QHostAddress &host() const throw();
00376     void setHost(const QHostAddress &addr);
00378     FXushort port() const throw();
00380     void setPort(FXushort port);
00381 
00383     virtual void open(const FXString &password=FXString::nullStr())=0;
00385     virtual void close()=0;
00387     virtual TnFXSQLDBStatementRef prepare(const FXString &text)=0;
00388 
00390     virtual TnFXSQLDBCursorRef execute(const FXString &text, FXuint flags=2/*TnFXSQLDBCursor::IsDynamic*/|4/*TnFXSQLDBCursor::ForwardOnly*/, QWaitCondition *latch=0);
00392     virtual void immediate(const FXString &text);
00393 
00395     virtual void synchronise();
00396 };
00397 
00407 class FXSQLMODULEAPI TnFXSQLDBTransaction
00408 {
00409     TnFXSQLDB *mydb;
00410     FXString myname;
00411     bool dismissed;
00412     void command(const char *_cmd)
00413     {
00414         if(mydb)
00415         {
00416             FXString cmd(_cmd);
00417             if(!myname.empty()) cmd.append(" '"+myname+"'");
00418             cmd.append(";");
00419             mydb->immediate(cmd);
00420         }
00421     }
00422     TnFXSQLDBTransaction(const TnFXSQLDBTransaction &);
00423     TnFXSQLDBTransaction &operator=(const TnFXSQLDBTransaction &);
00424 public:
00426     TnFXSQLDBTransaction(TnFXSQLDB *db, const FXString &name=FXString::nullStr()) : mydb(db), myname(name), dismissed(false) { command("BEGIN TRANSACTION"); }
00427     TnFXSQLDBTransaction(FXAutoPtr<TnFXSQLDB> &db, const FXString &name=FXString::nullStr()) : mydb(&(*db)), myname(name), dismissed(false) { command("BEGIN TRANSACTION"); }
00428     ~TnFXSQLDBTransaction()
00429     {
00430         rollback();
00431     }
00433     void commit()
00434     {
00435         if(mydb && !dismissed)
00436         {
00437             command("COMMIT TRANSACTION");
00438             dismissed=true;
00439         }
00440     }
00442     void rollback()
00443     {
00444         if(mydb && !dismissed)
00445         {
00446             command("ROLLBACK TRANSACTION");
00447             dismissed=true;
00448         }
00449     }
00450 };
00451 
00468 struct TnFXSQLDBCursorPrivate;
00469 class FXSQLMODULEAPI TnFXSQLDBCursor : public FXRefedObject<int>
00470 {
00471     TnFXSQLDBCursorPrivate *p;
00472     TnFXSQLDBCursor &operator=(const TnFXSQLDBCursor &o);
00473 protected:
00474     TnFXSQLDBCursor(FXuint flags, TnFXSQLDBStatement *parent, QWaitCondition *latch, FXuint columns);
00475     TnFXSQLDBCursor(const TnFXSQLDBCursor &o);
00476     void int_setInternals(FXint *rows, FXuint *flags=0, FXuint *columns=0, QWaitCondition *latch=0);
00477     void int_setRowsReady(FXint start, FXint end);
00478     void int_setAtEnd(bool atend);
00479 public:
00480     virtual ~TnFXSQLDBCursor();
00482     virtual TnFXSQLDBCursorRef copy() const=0;
00483 
00485     enum Flags
00486     {   // If you change these remember to adjust TnFXSQLDB above
00487         IsStatic=1,         
00488         IsDynamic=2,        
00489         ForwardOnly=4       
00490     };
00491 
00493     FXuint flags() const throw();
00495     TnFXSQLDBStatement *statement() const throw();
00497     QWaitCondition *resultsLatch() const throw();
00499     FXuint columns() const throw();
00501     FXint rows() const throw();
00503     bool rowsReady(FXint &start, FXint &end) const throw();
00504 
00506     bool atEnd() const throw();
00508     FXint at() const throw();
00512     virtual FXint at(FXint newrow);
00514     virtual FXint backwards();
00516     FXint prev() { return backwards(); }
00518     virtual FXint forwards();
00520     FXint next() { return forwards(); }
00521 
00524     virtual void type(TnFXSQLDB::SQLDataType &datatype, FXint &size, FXuint no) const=0;
00526     virtual TnFXSQLDBColumnRef header(FXuint no)=0;
00528     virtual TnFXSQLDBColumnRef data(FXuint no)=0;
00529 };
00530 
00554 struct TnFXSQLDBStatementPrivate;
00555 class FXSQLMODULEAPI TnFXSQLDBStatement : public FXRefedObject<int>
00556 {
00557     TnFXSQLDBStatementPrivate *p;
00558     TnFXSQLDBStatement &operator=(const TnFXSQLDBStatement &o);
00559 protected:
00560     TnFXSQLDBStatement(TnFXSQLDB *parent, const FXString &text);
00561     TnFXSQLDBStatement(const TnFXSQLDBStatement &o);
00562 public:
00563     virtual ~TnFXSQLDBStatement();
00565     virtual TnFXSQLDBStatementRef copy() const=0;
00566 
00568     TnFXSQLDB *driver() const throw();
00570     const FXString &text() const throw();
00571 
00573     virtual FXint parameters() const=0;
00575     virtual FXint parameterIdx(const FXString &name) const=0;
00577     virtual FXString parameterName(FXint idx) const=0;
00582     virtual TnFXSQLDBStatement &bind(FXint idx, TnFXSQLDB::SQLDataType datatype, void *data);
00583 private:
00584 #if defined(_MSC_VER) && _MSC_VER<=1400 && !defined(__INTEL_COMPILER) && !defined(__GCCXML__)
00585 #if _MSC_VER<=1310 
00586     // MSVC7.1 and earlier just won't friend templates with specialisations :(
00587     friend struct TnFXSQLDBImpl::DoSerialise;
00588 #else
00589     // MSVC8.0 is even worse :(. Just give up and call it public
00590 public:
00591 #endif
00592 #else
00593     // This being the proper ISO C++ form
00594     template<bool unknownType, typename type> friend struct TnFXSQLDBImpl::DoSerialise;
00595 #endif
00596     void int_bindUnknownBLOB(FXint idx, FXAutoPtr<QBuffer> buff);
00597 public:
00599     template<typename type> TnFXSQLDBStatement &bind(FXint idx, const type &v)
00600     {
00601         typedef TnFXSQLDB::CPPToSQL92Type<type> sql92type;
00602         TnFXSQLDBImpl::BindImpl<sql92type::value, -1!=sql92type::unsignedIntIdx, type>(this, idx,
00603             TnFXSQLDBImpl::checkForOverflow<-1!=sql92type::unsignedIntIdx, type, typename sql92type::signedIntEquiv>::Do(&v), v);
00604         return *this;
00605     }
00607     TnFXSQLDBStatement &bind(FXint idx)
00608     {
00609         bind(idx, TnFXSQLDB::Null, 0);
00610         return *this;
00611     }
00615     template<typename type> FXint bind(const FXString &name, const type &v)
00616     {
00617         FXint idx=parameterIdx(name);
00618         bind<type>(idx, v);
00619         return idx;
00620     }
00622     FXint bind(const FXString &name)
00623     {
00624         FXint idx=parameterIdx(name);
00625         bind(idx, TnFXSQLDB::Null, 0);
00626         return idx;
00627     }
00631     virtual TnFXSQLDBCursorRef execute(FXuint flags=TnFXSQLDBCursor::IsDynamic|TnFXSQLDBCursor::ForwardOnly, QWaitCondition *latch=0)=0;
00633     virtual void immediate()=0;
00634 };
00635 
00636 
00637 namespace TnFXSQLDBImpl
00638 {   // You can specialise these to use custom dumping routines like Tn does
00639     template<bool override, typename type> struct SerialiseUnknownBLOB
00640     {
00641         SerialiseUnknownBLOB(FXStream &s, const type &v)
00642         {   // Simply dump
00643             s << const_cast<type &>(v);
00644         }
00645     };
00646     template<bool override, typename type> struct DeserialiseUnknownBLOB
00647     {
00648         DeserialiseUnknownBLOB(type &v, FXStream &s)
00649         {   // Simply load
00650             s >> v;
00651         }
00652     };
00653 
00654 
00655 
00656     template<int sql92type, bool isUnsignedInt, typename type> struct BindImpl
00657     {   // It's known and not an unsigned int, so simply pass as a void *
00658         BindImpl(TnFXSQLDBStatement *s, FXint idx, bool upgrade, const type &v)
00659         {
00660             TnFXSQLDB::SQLDataType datatype=TnFXSQLDB::toSQL92Type<type>(&v) ;
00661             s->bind(idx, datatype, (void *) &v);
00662         }
00663     };
00664     template<int sql92type, typename type> struct BindImpl<sql92type, true, type>
00665     {   // It's known and is an unsigned int, so simply pass as a void *
00666         BindImpl(TnFXSQLDBStatement *s, FXint idx, bool upgrade, const type &v)
00667         {
00668             TnFXSQLDB::SQLDataType datatype=TnFXSQLDB::toSQL92Type<type>(&v) ;
00669             if(upgrade)
00670             {   // Need to copy to higher container to stay endian safe
00671                 typedef typename Generic::TL::at<TnFXSQLDB::CPPDataTypes, sql92type+1>::value biggerContainer;
00672                 biggerContainer bv=v;
00673                 s->bind(idx, datatype, (void *) &bv);
00674             }
00675             else
00676                 s->bind(idx, datatype, (void *) &v);
00677         }
00678     };
00679     template<bool canSerialise, typename type> struct DoSerialise
00680     {
00681         DoSerialise(TnFXSQLDBStatement *s, FXint idx, const type &v)
00682         {
00683             FXERRG(FXString("No operator<< found for type %1").arg(Generic::typeInfo<type>().name()), 0, FXERRH_ISDEBUG);
00684         }
00685     };
00686     template<typename type> struct DoSerialise<true, type>
00687     {
00688         DoSerialise(TnFXSQLDBStatement *s, FXint idx, const type &v)
00689         {
00690             FXAutoPtr<QBuffer> buff;
00691             FXERRHM(buff=new QBuffer);
00692             buff->open(IO_WriteOnly);
00693             FXStream ds(PtrPtr(buff));
00694             SerialiseUnknownBLOB<true, type>(ds, v);
00695             s->int_bindUnknownBLOB(idx, buff);
00696         }
00697     };
00698     template<bool isUnsignedInt, typename type> struct BindImpl<-1, isUnsignedInt, type>
00699     {   // It's some unknown type. Try serialising it
00700         BindImpl(TnFXSQLDBStatement *s, FXint idx, bool upgrade, const type &v)
00701         {
00702             DoSerialise<Generic::hasSerialise<type>::value, type>(s, idx, v);
00703         }
00704     };
00705     template<bool isUnsignedInt> struct BindImpl<-1, isUnsignedInt, const char *>
00706     {   // A string literal. Convert to FXString and pass
00707         BindImpl(TnFXSQLDBStatement *s, FXint idx, bool upgrade, const char *&v)
00708         {
00709             FXString l(v);
00710             TnFXSQLDB::SQLDataType datatype=TnFXSQLDB::toSQL92Type<FXString>(&l) ;
00711             s->bind(idx, datatype, (void *) &l);
00712         }
00713     };
00714 
00715 
00716 
00717     template<bool isConvertible, typename rettype, typename srctype> struct GetImpl
00718     {
00719         GetImpl(rettype *dst, const srctype *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00720         {   // For the common case when no conversion exists between src and dst
00721             FXERRG(FXString("No conversion exists from %1 to %2").arg(Generic::typeInfo<srctype>().name()).arg(Generic::typeInfo<rettype>().name()), 0, FXERRH_ISDEBUG);
00722         }
00723     };
00724     template<typename rettype, typename srctype> struct GetImpl<true, rettype, srctype>
00725     {   // Good for anything with an implicit conversion available
00726         GetImpl(rettype *dst, const srctype *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00727         {   // Set dest equal to src, invoking appropriate conversions
00728             *dst=*src;
00729         }
00730     };
00731     template<typename rettype> struct GetImpl<true, rettype, FXString>
00732     {   // To avoid excessive memory copying, we don't construct FXString until the last moment
00733         GetImpl(rettype *dst, const FXString *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00734         {
00735             if(TnFXSQLDB::VarChar==sqldatatype || TnFXSQLDB::Char==sqldatatype)
00736             {
00737                 *dst=FXString((const FXchar *) src, (FXint) srcsize);
00738             }
00739             else if(TnFXSQLDB::WVarChar==sqldatatype || TnFXSQLDB::WChar==sqldatatype)
00740             {
00741                 //*dst=FXString((FXnchar *) src, (FXint) srcsize);
00742                 assert(0);
00743             }
00744             else { assert(0); }
00745         }
00746     };
00747     template<> struct GetImpl<false, const char *, FXString>
00748     {   // This being the by-reference accessor
00749         GetImpl(const char **dst, const FXString *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00750         {
00751             if(TnFXSQLDB::VarChar==sqldatatype || TnFXSQLDB::Char==sqldatatype)
00752             {
00753                 *dst=(const FXchar *) src;
00754             }
00755             else
00756                 *dst=0;
00757         }
00758     };
00759     template<> struct GetImpl<true, QByteArray, QByteArray>
00760     {   // To avoid excessive memory copying, construct the QByteArray to directly point at this data
00761         GetImpl(QByteArray *dst, const QByteArray *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00762         {
00763             dst->setRawData((FXuchar *) src, (FXuint) srcsize, true);
00764         }
00765     };
00766     template<bool canDeserialise, typename rettype> struct DoDeserialise
00767     {
00768         DoDeserialise(rettype *dst, FXuchar *src, FXuint srcsize)
00769         {
00770             FXERRG(FXString("No operator>> found for type %1").arg(Generic::typeInfo<rettype>().name()), 0, FXERRH_ISDEBUG);
00771         }
00772     };
00773     template<typename rettype> struct DoDeserialise<true, rettype>
00774     {
00775         DoDeserialise(rettype *dst, FXuchar *src, FXuint srcsize)
00776         {
00777             QByteArray ba(src, srcsize);
00778             QBuffer buff(ba);
00779             buff.open(IO_ReadOnly);
00780             FXStream ds(&buff);
00781             DeserialiseUnknownBLOB<true, rettype>(*dst, ds);
00782         }
00783     };
00784     template<bool isConvertible, typename rettype> struct GetImpl<isConvertible, rettype, QByteArray>
00785     {   // This being the specialisation of BLOB to unknown type
00786         GetImpl(rettype *dst, const QByteArray *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00787         {
00788             DoDeserialise<Generic::hasDeserialise<rettype>::value, rettype>(dst, (FXuchar *) src, (FXuint) srcsize);
00789         }
00790     };
00791     template<typename rettype> struct Get
00792     {
00793         template<typename type> struct Source
00794         {   // rettype is the type we're storing to, type is the source type
00795             static void Do(rettype *dst, const void *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00796             {
00797                 GetImpl<Generic::convertible<rettype, type>::value, rettype, type>(dst, (const type *) src, sqldatatype, srcsize);
00798             }
00799         };
00800         static void Invoke(rettype *dst, const void *src, TnFXSQLDB::SQLDataType sqldatatype, FXuval srcsize)
00801         {
00802             TnFXSQLDB::toCPPType<Source>(sqldatatype, dst, src, sqldatatype, srcsize);
00803         }
00804     };
00805 }
00806 
00822 class FXSQLMODULEAPI TnFXSQLDBColumn : public FXRefedObject<int>
00823 {
00824 protected:
00825     FXint myflags;
00826     TnFXSQLDBCursorRef myparent;
00827     FXuint mycolumn;
00828     FXint myrow;
00829     TnFXSQLDB::SQLDataType mytype;
00830     const void *mydata;
00831     FXuval mydatalen;
00832     union Scratch           // Some scratch space to avoid memory allocation for small types
00833     {
00834         FXchar tinyint;
00835         FXshort smallint;
00836         FXint integer;
00837         FXlong bigint;
00838         FXfloat real;
00839         FXdouble double_;
00840         char timestamp[sizeof(FXTime)];
00841     } scratch;
00842     TnFXSQLDBColumn(const TnFXSQLDBColumn &o) : myflags(o.myflags), myparent(o.myparent), mycolumn(o.mycolumn), myrow(o.myrow), mytype(o.mytype),
00843         mydata(o.mydata), mydatalen(o.mydatalen) { }
00844 public:
00845     TnFXSQLDBColumn(FXuint flags, TnFXSQLDBCursor *parent, FXuint column, FXint row, TnFXSQLDB::SQLDataType type=TnFXSQLDB::Null)
00846         : myflags(flags), myparent(parent), mycolumn(column), myrow(row), mytype(type), mydata(0), mydatalen(0) { }
00847     virtual ~TnFXSQLDBColumn() { }
00849     virtual TnFXSQLDBColumnRef copy() const=0;
00851     enum Flags
00852     {
00853         IsHeader=1          
00854     };
00855 
00857     FXuint flags() const throw() { return myflags; }
00859     TnFXSQLDBCursor *cursor() const throw() { return const_cast<TnFXSQLDBCursor *>(PtrPtr(myparent)); }
00861     FXuint column() const throw() { return mycolumn; }
00863     FXint row() const throw() { return myrow; }
00865     TnFXSQLDBColumnRef header() const { return cursor()->header(column()); }
00867     TnFXSQLDB::SQLDataType type() const throw() { return mytype; }
00869     const void *data() const throw() { return mydata; }
00871     FXuval size() const throw() { return mydatalen; }
00875     TnFXSQLDB::SQLDataType effectiveType() const throw()
00876     {
00877         if(TnFXSQLDB::Decimal==mytype || TnFXSQLDB::Numeric==mytype)
00878             return (TnFXSQLDB::SQLDataType)(TnFXSQLDB::TinyInt+fxbitscan((FXulong) mydatalen));
00879         if(TnFXSQLDB::Float==mytype)
00880             return (TnFXSQLDB::SQLDataType)(TnFXSQLDB::Real-2+fxbitscan((FXulong) mydatalen));
00881         return mytype;
00882     }
00883 
00886     template<class T> void get(T &dst) const
00887     {   // Our problem is that we must make the rvalue for the operator= the
00888         // type that it is actually stored as
00889         TnFXSQLDB::SQLDataType coldatatype=effectiveType();
00890         TnFXSQLDBImpl::Get<T>::Invoke(&dst, mydata, coldatatype, mydatalen);
00891     }
00893     template<class T> T get() const
00894     {
00895         T ret;
00896         get<T>(ret);
00897         return ret;
00898     }
00899 };
00900 
00901 
00902 
00911 struct TnFXSQLDBRegistryPrivate;
00912 class FXSQLMODULEAPI TnFXSQLDBRegistry
00913 {
00914     friend struct TnFXSQLDBRegistryPrivate;
00915     TnFXSQLDBRegistryPrivate *p;
00916     TnFXSQLDBRegistry(const TnFXSQLDBRegistry &);
00917     TnFXSQLDBRegistry &operator=(const TnFXSQLDBRegistry &);
00918     typedef FXAutoPtr<TnFXSQLDB> (*createSpec)(const FXString &dbname, const FXString &user, const QHostAddress &host, FXushort port);
00919     void int_register(const FXString &name, createSpec create);
00920     void int_deregister(const FXString &name, createSpec create);
00921 public:
00922     TnFXSQLDBRegistry();
00923     ~TnFXSQLDBRegistry();
00924 
00926     static TnFXSQLDBRegistry *processRegistry();
00928     QStringList drivers() const;
00930     FXAutoPtr<TnFXSQLDB> instantiate(const FXString &name, const FXString &dbname=FXString::nullStr(), const FXString &user=FXString::nullStr(), const QHostAddress &host=QHOSTADDRESS_LOCALHOST, FXushort port=0) const;
00932     static FXAutoPtr<TnFXSQLDB> make(const FXString &name, const FXString &dbname=FXString::nullStr(), const FXString &user=FXString::nullStr(), const QHostAddress &host=QHOSTADDRESS_LOCALHOST, FXushort port=0)
00933     {
00934         return processRegistry()->instantiate(name, dbname, user, host, port);
00935     }
00936 
00937     template<class type> struct Register
00938     {
00939         static FXAutoPtr<TnFXSQLDB> create(const FXString &dbname, const FXString &user, const QHostAddress &host, FXushort port) { return new type(dbname, user, host, port); }
00940         Register() { processRegistry()->int_register(type::MyName, create); }
00941         ~Register() { processRegistry()->int_deregister(type::MyName, create); }
00942     };
00943     template<class type> friend struct Register;
00944 };
00945 
00946 
00947 #ifdef _MSC_VER
00948 #pragma warning(pop)
00949 #endif
00950 
00951 }
00952 
00953 #endif
00954 #endif

(C) 2002-2009 Niall Douglas. Some parts (C) to assorted authors.
Generated on Fri Nov 20 18:31:26 2009 for TnFOX by doxygen v1.4.7