/////////////////////////////////////////////////////////////////////////////// // // File : $Id: _ibpp.h,v 1.2 2007/05/17 08:37:05 faust Exp $ // Subject : IBPP internal declarations // /////////////////////////////////////////////////////////////////////////////// // // (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) // // The contents of this file are subject to the IBPP License (the "License"); // you may not use this file except in compliance with the License. You may // obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' // file which must have been distributed along with this file. // // This software, distributed under the License, is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // /////////////////////////////////////////////////////////////////////////////// // // COMMENTS // // * 'Internal declarations' means everything used to implement ibpp. This // file and its contents is NOT needed by users of the library. All those // declarations are wrapped in a namespace : 'ibpp_internals'. // * Tabulations should be set every four characters when editing this file. // /////////////////////////////////////////////////////////////////////////////// #ifndef __INTERNAL_IBPP_H__ #define __INTERNAL_IBPP_H__ #include "ibpp.h" #if defined(__BCPLUSPLUS__) || defined(_MSC_VER) || defined(__DMC__) #define HAS_HDRSTOP #endif #if (defined(__GNUC__) && defined(IBPP_WINDOWS)) // Setting flags for ibase.h -- using GCC/Cygwin/MinGW on Win32 #ifndef _MSC_VER #define _MSC_VER 1299 #endif #ifndef _WIN32 #define _WIN32 1 #endif #endif #include "ibase.h" // From Firebird 1.x or InterBase 6.x installation #if (defined(__GNUC__) && defined(IBPP_WINDOWS)) // UNSETTING flags used above for ibase.h -- Huge conflicts with libstdc++ ! #undef _MSC_VER #undef _WIN32 #endif #ifdef IBPP_WINDOWS #include #endif //#include #include #include #include #include #ifdef _DEBUG #define ASSERTION(x) {if (!(x)) {throw LogicExceptionImpl("ASSERTION", \ "'"#x"' is not verified at %s, line %d", \ __FILE__, __LINE__);}} #else #define ASSERTION(x) /* x */ #endif // Fix to famous MSVC 6 variable scope bug #if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300 #define for if(true)for #endif namespace ibpp_internals { enum flush_debug_stream_type {fds}; #ifdef _DEBUG struct DebugStream : public std::stringstream { // next two operators fix some g++ and vc++ related problems std::ostream& operator<< (const char* p) { static_cast(*this)<< p; return *this; } std::ostream& operator<< (const std::string& p) { static_cast(*this)<< p; return *this; } DebugStream& operator=(const DebugStream&) {return *this;} DebugStream(const DebugStream&) {} DebugStream() {} }; std::ostream& operator<< (std::ostream& a, flush_debug_stream_type); #else struct DebugStream { template DebugStream& operator<< (const T&) { return *this; } // for manipulators DebugStream& operator<< (std::ostream&(*)(std::ostream&)) { return *this; } }; #endif // _DEBUG class DatabaseImpl; class TransactionImpl; class StatementImpl; class BlobImpl; class ArrayImpl; class EventsImpl; // Native data types typedef enum {ivArray, ivBlob, ivDate, ivTime, ivTimestamp, ivString, ivInt16, ivInt32, ivInt64, ivFloat, ivDouble, ivBool, ivDBKey, ivByte} IITYPE; // // Those are the Interbase C API prototypes that we use // Taken 'asis' from IBASE.H, prefix 'isc_' replaced with 'proto_', // and 'typedef' preprended... // typedef ISC_STATUS ISC_EXPORT proto_create_database (ISC_STATUS *, short, char *, isc_db_handle *, short, char *, short); typedef ISC_STATUS ISC_EXPORT proto_attach_database (ISC_STATUS *, short, char *, isc_db_handle *, short, char *); typedef ISC_STATUS ISC_EXPORT proto_detach_database (ISC_STATUS *, isc_db_handle *); typedef ISC_STATUS ISC_EXPORT proto_drop_database (ISC_STATUS *, isc_db_handle *); typedef ISC_STATUS ISC_EXPORT proto_database_info (ISC_STATUS *, isc_db_handle *, short, char *, short, char *); typedef ISC_STATUS ISC_EXPORT proto_dsql_execute_immediate (ISC_STATUS *, isc_db_handle *, isc_tr_handle *, unsigned short, char *, unsigned short, XSQLDA *); typedef ISC_STATUS ISC_EXPORT proto_open_blob2 (ISC_STATUS *, isc_db_handle *, isc_tr_handle *, isc_blob_handle *, ISC_QUAD *, short, char *); typedef ISC_STATUS ISC_EXPORT proto_create_blob2 (ISC_STATUS *, isc_db_handle *, isc_tr_handle *, isc_blob_handle *, ISC_QUAD *, short, char *); typedef ISC_STATUS ISC_EXPORT proto_close_blob (ISC_STATUS *, isc_blob_handle *); typedef ISC_STATUS ISC_EXPORT proto_cancel_blob (ISC_STATUS *, isc_blob_handle *); typedef ISC_STATUS ISC_EXPORT proto_get_segment (ISC_STATUS *, isc_blob_handle *, unsigned short *, unsigned short, char *); typedef ISC_STATUS ISC_EXPORT proto_put_segment (ISC_STATUS *, isc_blob_handle *, unsigned short, char *); typedef ISC_STATUS ISC_EXPORT proto_blob_info (ISC_STATUS *, isc_blob_handle *, short, char *, short, char *); typedef ISC_STATUS ISC_EXPORT proto_array_lookup_bounds (ISC_STATUS *, isc_db_handle *, isc_tr_handle *, char *, char *, ISC_ARRAY_DESC *); typedef ISC_STATUS ISC_EXPORT proto_array_get_slice (ISC_STATUS *, isc_db_handle *, isc_tr_handle *, ISC_QUAD *, ISC_ARRAY_DESC *, void *, ISC_LONG *); typedef ISC_STATUS ISC_EXPORT proto_array_put_slice (ISC_STATUS *, isc_db_handle *, isc_tr_handle *, ISC_QUAD *, ISC_ARRAY_DESC *, void *, ISC_LONG *); typedef ISC_LONG ISC_EXPORT proto_vax_integer (char *, short); typedef ISC_LONG ISC_EXPORT proto_sqlcode (ISC_STATUS *); typedef void ISC_EXPORT proto_sql_interprete (short, char *, short); typedef ISC_STATUS ISC_EXPORT proto_interprete (char *, ISC_STATUS * *); typedef ISC_STATUS ISC_EXPORT proto_que_events (ISC_STATUS *, isc_db_handle *, ISC_LONG *, short, char *, isc_callback, void *); typedef ISC_STATUS ISC_EXPORT proto_cancel_events (ISC_STATUS *, isc_db_handle *, ISC_LONG *); typedef ISC_STATUS ISC_EXPORT proto_start_multiple (ISC_STATUS *, isc_tr_handle *, short, void *); typedef ISC_STATUS ISC_EXPORT proto_commit_transaction (ISC_STATUS *, isc_tr_handle *); typedef ISC_STATUS ISC_EXPORT proto_commit_retaining (ISC_STATUS *, isc_tr_handle *); typedef ISC_STATUS ISC_EXPORT proto_rollback_transaction (ISC_STATUS *, isc_tr_handle *); typedef ISC_STATUS ISC_EXPORT proto_rollback_retaining (ISC_STATUS *, isc_tr_handle *); /////////// typedef ISC_STATUS ISC_EXPORT proto_dsql_allocate_statement (ISC_STATUS *, isc_db_handle *, isc_stmt_handle *); typedef ISC_STATUS ISC_EXPORT proto_dsql_describe (ISC_STATUS *, isc_stmt_handle *, unsigned short, XSQLDA *); typedef ISC_STATUS ISC_EXPORT proto_dsql_describe_bind (ISC_STATUS *, isc_stmt_handle *, unsigned short, XSQLDA *); typedef ISC_STATUS ISC_EXPORT proto_dsql_execute (ISC_STATUS *, isc_tr_handle *, isc_stmt_handle *, unsigned short, XSQLDA *); typedef ISC_STATUS ISC_EXPORT proto_dsql_execute2 (ISC_STATUS *, isc_tr_handle *, isc_stmt_handle *, unsigned short, XSQLDA *, XSQLDA *); typedef ISC_STATUS ISC_EXPORT proto_dsql_fetch (ISC_STATUS *, isc_stmt_handle *, unsigned short, XSQLDA *); typedef ISC_STATUS ISC_EXPORT proto_dsql_free_statement (ISC_STATUS *, isc_stmt_handle *, unsigned short); typedef ISC_STATUS ISC_EXPORT proto_dsql_prepare (ISC_STATUS *, isc_tr_handle *, isc_stmt_handle *, unsigned short, char *, unsigned short, XSQLDA *); typedef ISC_STATUS ISC_EXPORT proto_dsql_set_cursor_name (ISC_STATUS *, isc_stmt_handle *, char *, unsigned short); typedef ISC_STATUS ISC_EXPORT proto_dsql_sql_info (ISC_STATUS *, isc_stmt_handle *, short, char *, short, char *); typedef void ISC_EXPORT proto_decode_date (ISC_QUAD *, void *); typedef void ISC_EXPORT proto_encode_date (void *, ISC_QUAD *); typedef int ISC_EXPORT proto_add_user (ISC_STATUS *, USER_SEC_DATA *); typedef int ISC_EXPORT proto_delete_user (ISC_STATUS *, USER_SEC_DATA *); typedef int ISC_EXPORT proto_modify_user (ISC_STATUS *, USER_SEC_DATA *); // // Those API are only available in versions 6.x of the GDS32.DLL // typedef ISC_STATUS ISC_EXPORT proto_service_attach (ISC_STATUS *, unsigned short, char *, isc_svc_handle *, unsigned short, char *); typedef ISC_STATUS ISC_EXPORT proto_service_detach (ISC_STATUS *, isc_svc_handle *); typedef ISC_STATUS ISC_EXPORT proto_service_query (ISC_STATUS *, isc_svc_handle *, isc_resv_handle *, unsigned short, char *, unsigned short, char *, unsigned short, char *); typedef ISC_STATUS ISC_EXPORT proto_service_start (ISC_STATUS *, isc_svc_handle *, isc_resv_handle *, unsigned short, char*); typedef void ISC_EXPORT proto_decode_sql_date (ISC_DATE *, void *); typedef void ISC_EXPORT proto_decode_sql_time (ISC_TIME *, void *); typedef void ISC_EXPORT proto_decode_timestamp (ISC_TIMESTAMP *, void *); typedef void ISC_EXPORT proto_encode_sql_date (void *, ISC_DATE *); typedef void ISC_EXPORT proto_encode_sql_time (void *, ISC_TIME *); typedef void ISC_EXPORT proto_encode_timestamp (void *, ISC_TIMESTAMP *); // // Internal binding structure to the GDS32 DLL // struct GDS { // Attributes bool mReady; int mGDSVersion; // Version of the GDS32.DLL (50 for 5.0, 60 for 6.0) #ifdef IBPP_WINDOWS HMODULE mHandle; // The GDS32.DLL HMODULE std::string mSearchPaths; // Optional additional search paths #endif GDS* Call(); // GDS32 Entry Points proto_create_database* m_create_database; proto_attach_database* m_attach_database; proto_detach_database* m_detach_database; proto_drop_database* m_drop_database; proto_database_info* m_database_info; proto_dsql_execute_immediate* m_dsql_execute_immediate; proto_open_blob2* m_open_blob2; proto_create_blob2* m_create_blob2; proto_close_blob* m_close_blob; proto_cancel_blob* m_cancel_blob; proto_get_segment* m_get_segment; proto_put_segment* m_put_segment; proto_blob_info* m_blob_info; proto_array_lookup_bounds* m_array_lookup_bounds; proto_array_get_slice* m_array_get_slice; proto_array_put_slice* m_array_put_slice; proto_vax_integer* m_vax_integer; proto_sqlcode* m_sqlcode; proto_sql_interprete* m_sql_interprete; proto_interprete* m_interprete; proto_que_events* m_que_events; proto_cancel_events* m_cancel_events; proto_start_multiple* m_start_multiple; proto_commit_transaction* m_commit_transaction; proto_commit_retaining* m_commit_retaining; proto_rollback_transaction* m_rollback_transaction; proto_rollback_retaining* m_rollback_retaining; proto_dsql_allocate_statement* m_dsql_allocate_statement; proto_dsql_describe* m_dsql_describe; proto_dsql_describe_bind* m_dsql_describe_bind; proto_dsql_prepare* m_dsql_prepare; proto_dsql_execute* m_dsql_execute; proto_dsql_execute2* m_dsql_execute2; proto_dsql_fetch* m_dsql_fetch; proto_dsql_free_statement* m_dsql_free_statement; proto_dsql_set_cursor_name* m_dsql_set_cursor_name; proto_dsql_sql_info* m_dsql_sql_info; //proto_decode_date* m_decode_date; //proto_encode_date* m_encode_date; //proto_add_user* m_add_user; //proto_delete_user* m_delete_user; //proto_modify_user* m_modify_user; proto_service_attach* m_service_attach; proto_service_detach* m_service_detach; proto_service_start* m_service_start; proto_service_query* m_service_query; //proto_decode_sql_date* m_decode_sql_date; //proto_decode_sql_time* m_decode_sql_time; //proto_decode_timestamp* m_decode_timestamp; //proto_encode_sql_date* m_encode_sql_date; //proto_encode_sql_time* m_encode_sql_time; //proto_encode_timestamp* m_encode_timestamp; // Constructor (No need for a specific destructor) GDS() { mReady = false; mGDSVersion = 0; #ifdef IBPP_WINDOWS mHandle = 0; #endif }; }; extern GDS gds; // // Service Parameter Block (used to define a service) // class SPB { static const int BUFFERINCR; char* mBuffer; // Dynamically allocated SPB structure int mSize; // Its used size in bytes int mAlloc; // Its allocated size in bytes void Grow(int needed); // Alloc or grow the mBuffer public: void Insert(char); // Insert a single byte code void InsertString(char, int, const char*); // Insert a string, len can be defined as 1 or 2 bytes void InsertByte(char type, char data); void InsertQuad(char type, int32_t data); void Reset(); // Clears the SPB char* Self() { return mBuffer; } short Size() { return (short)mSize; } SPB() : mBuffer(0), mSize(0), mAlloc(0) { } ~SPB() { Reset(); } }; // // Database Parameter Block (used to define a database) // class DPB { static const int BUFFERINCR; char* mBuffer; // Dynamically allocated DPB structure int mSize; // Its used size in bytes int mAlloc; // Its allocated size in bytes void Grow(int needed); // Allocate or grow the mBuffer, so that // 'needed' bytes can be written (at least) public: void Insert(char, const char*); // Insert a new char* 'cluster' void Insert(char, int16_t); // Insert a new int16_t 'cluster' void Insert(char, bool); // Insert a new bool 'cluster' void Insert(char, char); // Insert a new byte 'cluster' void Reset(); // Clears the DPB char* Self() { return mBuffer; } short Size() { return (short)mSize; } DPB() : mBuffer(0), mSize(0), mAlloc(0) { } ~DPB() { Reset(); } }; // // Transaction Parameter Block (used to define a transaction) // class TPB { static const int BUFFERINCR; char* mBuffer; // Dynamically allocated TPB structure int mSize; // Its used size in bytes int mAlloc; // Its allocated size void Grow(int needed); // Alloc or re-alloc the mBuffer public: void Insert(char); // Insert a flag item void Insert(const std::string& data); // Insert a string (typically table name) void Reset(); // Clears the TPB char* Self() { return mBuffer; } int Size() { return mSize; } TPB() : mBuffer(0), mSize(0), mAlloc(0) { } ~TPB() { Reset(); } }; // // Used to receive (and process) a results buffer in various API calls // class RB { char* mBuffer; int mSize; char* FindToken(char token); char* FindToken(char token, char subtoken); public: void Reset(); int GetValue(char token); int GetCountValue(char token); int GetValue(char token, char subtoken); bool GetBool(char token); int GetString(char token, std::string& data); char* Self() { return mBuffer; } short Size() { return (short)mSize; } RB(); RB(int Size); ~RB(); }; // // Used to receive status info from API calls // class IBS { mutable ISC_STATUS mVector[20]; mutable std::string mMessage; public: ISC_STATUS* Self() { return mVector; } bool Errors() { return (mVector[0] == 1 && mVector[1] > 0) ? true : false; } const char* ErrorMessage() const; int SqlCode() const; int EngineCode() const { return (mVector[0] == 1) ? (int)mVector[1] : 0; } void Reset(); IBS(); IBS(IBS&); // Copy Constructor ~IBS(); }; /////////////////////////////////////////////////////////////////////////////// // // Implementation of the "hidden" classes associated with their public // counterparts. Their private data and methods can freely change without // breaking the compatibility of the DLL. If they receive new public methods, // and those methods are reflected in the public class, then the compatibility // is broken. // /////////////////////////////////////////////////////////////////////////////// // // Hidden implementation of Exception classes. // /* std::exception | IBPP::Exception / \ / \ IBPP::LogicException ExceptionBase IBPP::SQLException | \ / | \ / | LogicExceptionImpl | SQLExceptionImpl | | IBPP::WrongType | \ | IBPP::WrongTypeImpl */ class ExceptionBase { // (((((((( OBJECT INTERNALS )))))))) protected: std::string mContext; // Exception context ("IDatabase::Drop") std::string mWhat; // Full formatted message void buildErrorMessage(const char* message); void raise(const std::string& context, const char* message, va_list argptr); public: // The following constructors are small and could be inlined, but for object // code compacity of the library it is much better to have them non-inlined. // The amount of code generated by compilers for a throw is well-enough. ExceptionBase() throw(); ExceptionBase(const ExceptionBase& copied) throw(); ExceptionBase& operator=(const ExceptionBase& copied) throw(); ExceptionBase(const std::string& context, const char* message = 0, ...) throw(); virtual ~ExceptionBase() throw(); // (((((((( OBJECT INTERFACE )))))))) virtual const char* Origin() const throw(); virtual const char* ErrorMessage() const throw(); virtual const char* what() const throw(); }; class LogicExceptionImpl : public IBPP::LogicException, public ExceptionBase { // (((((((( OBJECT INTERNALS )))))))) public: // The following constructors are small and could be inlined, but for object // code compacity of the library it is much better to have them non-inlined. // The amount of code generated by compilers for a throw is well-enough. LogicExceptionImpl() throw(); LogicExceptionImpl(const LogicExceptionImpl& copied) throw(); LogicExceptionImpl& operator=(const LogicExceptionImpl& copied) throw(); LogicExceptionImpl(const std::string& context, const char* message = 0, ...) throw(); virtual ~LogicExceptionImpl() throw (); // (((((((( OBJECT INTERFACE )))))))) // // The object public interface is partly implemented by inheriting from // the ExceptionBase class. public: virtual const char* Origin() const throw(); virtual const char* ErrorMessage() const throw(); virtual const char* what() const throw(); }; class SQLExceptionImpl : public IBPP::SQLException, public ExceptionBase { // (((((((( OBJECT INTERNALS )))))))) private: int mSqlCode; int mEngineCode; public: // The following constructors are small and could be inlined, but for object // code compacity of the library it is much better to have them non-inlined. // The amount of code generated by compilers for a throw is well-enough. SQLExceptionImpl() throw(); SQLExceptionImpl(const SQLExceptionImpl& copied) throw(); SQLExceptionImpl& operator=(const SQLExceptionImpl& copied) throw(); SQLExceptionImpl(const IBS& status, const std::string& context, const char* message = 0, ...) throw(); virtual ~SQLExceptionImpl() throw (); // (((((((( OBJECT INTERFACE )))))))) // // The object public interface is partly implemented by inheriting from // the ExceptionBase class. public: virtual const char* Origin() const throw(); virtual const char* ErrorMessage() const throw(); virtual const char* what() const throw(); virtual int SqlCode() const throw(); virtual int EngineCode() const throw(); }; class WrongTypeImpl : public IBPP::WrongType, public ExceptionBase { // (((((((( OBJECT INTERNALS )))))))) public: // The following constructors are small and could be inlined, but for object // code compacity of the library it is much better to have them non-inlined. // The amount of code generated by compilers for a throw is well-enough. WrongTypeImpl() throw(); WrongTypeImpl(const WrongTypeImpl& copied) throw(); WrongTypeImpl& operator=(const WrongTypeImpl& copied) throw(); WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType, const char* message = 0, ...) throw(); virtual ~WrongTypeImpl() throw (); // (((((((( OBJECT INTERFACE )))))))) // // The object public interface is partly implemented by inheriting from // the ExceptionBase class. public: virtual const char* Origin() const throw(); virtual const char* ErrorMessage() const throw(); virtual const char* what() const throw(); }; class ServiceImpl : public IBPP::IService { // (((((((( OBJECT INTERNALS )))))))) private: int mRefCount; // Reference counter isc_svc_handle mHandle; // InterBase API Service Handle std::string mServerName; // Nom du serveur std::string mUserName; // Nom de l'utilisateur std::string mUserPassword; // Mot de passe de l'utilisateur std::string mWaitMessage; // Progress message returned by WaitMsg() isc_svc_handle* GetHandlePtr() { return &mHandle; } void SetServerName(const char*); void SetUserName(const char*); void SetUserPassword(const char*); public: isc_svc_handle GetHandle() { return mHandle; } ServiceImpl(const std::string& ServerName, const std::string& UserName, const std::string& UserPassword); ~ServiceImpl(); // (((((((( OBJECT INTERFACE )))))))) public: void Connect(); bool Connected() { return mHandle == 0 ? false : true; } void Disconnect(); void GetVersion(std::string& version); void AddUser(const IBPP::User&); void GetUser(IBPP::User&); void GetUsers(std::vector&); void ModifyUser(const IBPP::User&); void RemoveUser(const std::string& username); void SetPageBuffers(const std::string& dbfile, int buffers); void SetSweepInterval(const std::string& dbfile, int sweep); void SetSyncWrite(const std::string& dbfile, bool); void SetReadOnly(const std::string& dbfile, bool); void SetReserveSpace(const std::string& dbfile, bool); void Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout); void Restart(const std::string& dbfile); void Sweep(const std::string& dbfile); void Repair(const std::string& dbfile, IBPP::RPF flags); void StartBackup(const std::string& dbfile, const std::string& bkfile, IBPP::BRF flags = IBPP::BRF(0)); void StartRestore(const std::string& bkfile, const std::string& dbfile, int pagesize, IBPP::BRF flags = IBPP::BRF(0)); const char* WaitMsg(); void Wait(); IBPP::IService* AddRef(); void Release(); }; class DatabaseImpl : public IBPP::IDatabase { // (((((((( OBJECT INTERNALS )))))))) int mRefCount; // Reference counter isc_db_handle mHandle; // InterBase API Session Handle std::string mServerName; // Server name std::string mDatabaseName; // Database name (path/file) std::string mUserName; // User name std::string mUserPassword; // User password std::string mRoleName; // Role used for the duration of the connection std::string mCharSet; // Character Set used for the connection std::string mCreateParams; // Other parameters (creation only) int mDialect; // 1 if IB5, 1 or 3 if IB6/FB1 std::vector mTransactions;// Table of Transaction* std::vector mStatements;// Table of Statement* std::vector mBlobs; // Table of Blob* std::vector mArrays; // Table of Array* std::vector mEvents; // Table of Events* public: isc_db_handle* GetHandlePtr() { return &mHandle; } isc_db_handle GetHandle() { return mHandle; } void AttachTransactionImpl(TransactionImpl*); void DetachTransactionImpl(TransactionImpl*); void AttachStatementImpl(StatementImpl*); void DetachStatementImpl(StatementImpl*); void AttachBlobImpl(BlobImpl*); void DetachBlobImpl(BlobImpl*); void AttachArrayImpl(ArrayImpl*); void DetachArrayImpl(ArrayImpl*); void AttachEventsImpl(EventsImpl*); void DetachEventsImpl(EventsImpl*); DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName, const std::string& UserName, const std::string& UserPassword, const std::string& RoleName, const std::string& CharSet, const std::string& CreateParams); ~DatabaseImpl(); // (((((((( OBJECT INTERFACE )))))))) public: const char* ServerName() const { return mServerName.c_str(); } const char* DatabaseName() const { return mDatabaseName.c_str(); } const char* Username() const { return mUserName.c_str(); } const char* UserPassword() const { return mUserPassword.c_str(); } const char* RoleName() const { return mRoleName.c_str(); } const char* CharSet() const { return mCharSet.c_str(); } const char* CreateParams() const { return mCreateParams.c_str(); } void Info(int* ODSMajor, int* ODSMinor, int* PageSize, int* Pages, int* Buffers, int* Sweep, bool* SyncWrites, bool* Reserve); void Statistics(int* Fetches, int* Marks, int* Reads, int* Writes); void Counts(int* Insert, int* Update, int* Delete, int* ReadIdx, int* ReadSeq); void Users(std::vector& users); int Dialect() { return mDialect; } void Create(int dialect); void Connect(); bool Connected() { return mHandle == 0 ? false : true; } void Inactivate(); void Disconnect(); void Drop(); IBPP::IDatabase* AddRef(); void Release(); }; class TransactionImpl : public IBPP::ITransaction { // (((((((( OBJECT INTERNALS )))))))) private: int mRefCount; // Reference counter isc_tr_handle mHandle; // Transaction InterBase std::vector mDatabases; // Tableau de IDatabase* std::vector mStatements; // Tableau de IStatement* std::vector mBlobs; // Tableau de IBlob* std::vector mArrays; // Tableau de Array* std::vector mTPBs; // Tableau de TPB void Init(); // A usage exclusif des constructeurs public: isc_tr_handle* GetHandlePtr() { return &mHandle; } isc_tr_handle GetHandle() { return mHandle; } void AttachStatementImpl(StatementImpl*); void DetachStatementImpl(StatementImpl*); void AttachBlobImpl(BlobImpl*); void DetachBlobImpl(BlobImpl*); void AttachArrayImpl(ArrayImpl*); void DetachArrayImpl(ArrayImpl*); void AttachDatabaseImpl(DatabaseImpl* dbi, IBPP::TAM am = IBPP::amWrite, IBPP::TIL il = IBPP::ilConcurrency, IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0)); void DetachDatabaseImpl(DatabaseImpl* dbi); TransactionImpl(DatabaseImpl* db, IBPP::TAM am = IBPP::amWrite, IBPP::TIL il = IBPP::ilConcurrency, IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0)); ~TransactionImpl(); // (((((((( OBJECT INTERFACE )))))))) public: void AttachDatabase(IBPP::Database db, IBPP::TAM am = IBPP::amWrite, IBPP::TIL il = IBPP::ilConcurrency, IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0)); void DetachDatabase(IBPP::Database db); void AddReservation(IBPP::Database db, const std::string& table, IBPP::TTR tr); void Start(); bool Started() { return mHandle == 0 ? false : true; } void Commit(); void Rollback(); void CommitRetain(); void RollbackRetain(); IBPP::ITransaction* AddRef(); void Release(); }; class RowImpl : public IBPP::IRow { // (((((((( OBJECT INTERNALS )))))))) private: int mRefCount; // Reference counter XSQLDA* mDescrArea; // XSQLDA descriptor itself std::vector mNumerics; // Temporary storage for Numerics std::vector mFloats; // Temporary storage for Floats std::vector mInt64s; // Temporary storage for 64 bits std::vector mInt32s; // Temporary storage for 32 bits std::vector mInt16s; // Temporary storage for 16 bits std::vector mBools; // Temporary storage for Bools std::vector mStrings; // Temporary storage for Strings std::vector mUpdated; // Which columns where updated (Set()) ? int mDialect; // Related database dialect DatabaseImpl* mDatabase; // Related Database (important for Blobs, ...) TransactionImpl* mTransaction; // Related Transaction (same remark) void SetValue(int, IITYPE, const void* value, int = 0); void* GetValue(int, IITYPE, void* = 0); public: void Free(); short AllocatedSize() { return mDescrArea->sqln; } void Resize(int n); void AllocVariables(); bool MissingValues(); // Returns wether one of the mMissing[] is true XSQLDA* Self() { return mDescrArea; } RowImpl& operator=(const RowImpl& copied); RowImpl(const RowImpl& copied); RowImpl(int dialect, int size, DatabaseImpl* db, TransactionImpl* tr); ~RowImpl(); // (((((((( OBJECT INTERFACE )))))))) public: void SetNull(int); void Set(int, bool); void Set(int, const char*); // c-strings void Set(int, const void*, int); // byte buffers void Set(int, const std::string&); void Set(int, int16_t); void Set(int, int32_t); void Set(int, int64_t); void Set(int, float); void Set(int, double); void Set(int, const IBPP::Timestamp&); void Set(int, const IBPP::Date&); void Set(int, const IBPP::Time&); void Set(int, const IBPP::DBKey&); void Set(int, const IBPP::Blob&); void Set(int, const IBPP::Array&); bool IsNull(int); bool Get(int, bool&); bool Get(int, char*); // c-strings, len unchecked bool Get(int, void*, int&); // byte buffers bool Get(int, std::string&); bool Get(int, int16_t&); bool Get(int, int32_t&); bool Get(int, int64_t&); bool Get(int, float&); bool Get(int, double&); bool Get(int, IBPP::Timestamp&); bool Get(int, IBPP::Date&); bool Get(int, IBPP::Time&); bool Get(int, IBPP::DBKey&); bool Get(int, IBPP::Blob&); bool Get(int, IBPP::Array&); bool IsNull(const std::string&); bool Get(const std::string&, bool&); bool Get(const std::string&, char*); // c-strings, len unchecked bool Get(const std::string&, void*, int&); // byte buffers bool Get(const std::string&, std::string&); bool Get(const std::string&, int16_t&); bool Get(const std::string&, int32_t&); bool Get(const std::string&, int64_t&); bool Get(const std::string&, float&); bool Get(const std::string&, double&); bool Get(const std::string&, IBPP::Timestamp&); bool Get(const std::string&, IBPP::Date&); bool Get(const std::string&, IBPP::Time&); bool Get(const std::string&, IBPP::DBKey&); bool Get(const std::string&, IBPP::Blob&); bool Get(const std::string&, IBPP::Array&); int ColumnNum(const std::string&); const char* ColumnName(int); const char* ColumnAlias(int); const char* ColumnTable(int); IBPP::SDT ColumnType(int); int ColumnSubtype(int); int ColumnSize(int); int ColumnScale(int); int Columns(); bool ColumnUpdated(int); bool Updated(); IBPP::Database DatabasePtr() const; IBPP::Transaction TransactionPtr() const; IBPP::IRow* Clone(); IBPP::IRow* AddRef(); void Release(); }; class StatementImpl : public IBPP::IStatement { // (((((((( OBJECT INTERNALS )))))))) private: friend class TransactionImpl; int mRefCount; // Reference counter isc_stmt_handle mHandle; // Statement Handle DatabaseImpl* mDatabase; // Attached database TransactionImpl* mTransaction; // Attached transaction RowImpl* mInRow; //bool* mInMissing; // Quels paramètres n'ont pas été spécifiés RowImpl* mOutRow; bool mResultSetAvailable; // Executed and result set is available bool mCursorOpened; // dsql_set_cursor_name was called IBPP::STT mType; // Type de requète std::string mSql; // Last SQL statement prepared or executed // Internal Methods void CursorFree(); public: // Properties and Attributes Access Methods isc_stmt_handle GetHandle() { return mHandle; } void AttachDatabaseImpl(DatabaseImpl*); void DetachDatabaseImpl(); void AttachTransactionImpl(TransactionImpl*); void DetachTransactionImpl(); StatementImpl(DatabaseImpl*, TransactionImpl*, const std::string&); ~StatementImpl(); // (((((((( OBJECT INTERFACE )))))))) public: void Prepare(const std::string& sql); void Execute(const std::string& sql); inline void Execute() { Execute(std::string()); } void ExecuteImmediate(const std::string&); void CursorExecute(const std::string& cursor, const std::string& sql); inline void CursorExecute(const std::string& cursor) { CursorExecute(cursor, std::string()); } bool Fetch(); bool Fetch(IBPP::Row&); int AffectedRows(); void Close(); // Free resources, attachments maintained std::string& Sql() { return mSql; } IBPP::STT Type() { return mType; } void SetNull(int); void Set(int, bool); void Set(int, const char*); // c-strings void Set(int, const void*, int); // byte buffers void Set(int, const std::string&); void Set(int, int16_t); void Set(int, int32_t); void Set(int, int64_t); void Set(int, float); void Set(int, double); void Set(int, const IBPP::Timestamp&); void Set(int, const IBPP::Date&); void Set(int, const IBPP::Time&); void Set(int, const IBPP::DBKey&); void Set(int, const IBPP::Blob&); void Set(int, const IBPP::Array&); bool IsNull(int); bool Get(int, bool*); bool Get(int, bool&); bool Get(int, char*); // c-strings, len unchecked bool Get(int, void*, int&); // byte buffers bool Get(int, std::string&); bool Get(int, int16_t*); bool Get(int, int16_t&); bool Get(int, int32_t*); bool Get(int, int32_t&); bool Get(int, int64_t*); bool Get(int, int64_t&); bool Get(int, float*); bool Get(int, float&); bool Get(int, double*); bool Get(int, double&); bool Get(int, IBPP::Timestamp&); bool Get(int, IBPP::Date&); bool Get(int, IBPP::Time&); bool Get(int, IBPP::DBKey&); bool Get(int, IBPP::Blob&); bool Get(int, IBPP::Array&); bool IsNull(const std::string&); bool Get(const std::string&, bool*); bool Get(const std::string&, bool&); bool Get(const std::string&, char*); // c-strings, len unchecked bool Get(const std::string&, void*, int&); // byte buffers bool Get(const std::string&, std::string&); bool Get(const std::string&, int16_t*); bool Get(const std::string&, int16_t&); bool Get(const std::string&, int32_t*); bool Get(const std::string&, int32_t&); bool Get(const std::string&, int64_t*); bool Get(const std::string&, int64_t&); bool Get(const std::string&, float*); bool Get(const std::string&, float&); bool Get(const std::string&, double*); bool Get(const std::string&, double&); bool Get(const std::string&, IBPP::Timestamp&); bool Get(const std::string&, IBPP::Date&); bool Get(const std::string&, IBPP::Time&); bool Get(const std::string&, IBPP::DBKey&); bool Get(const std::string&, IBPP::Blob&); bool Get(const std::string&, IBPP::Array&); int ColumnNum(const std::string&); int ColumnNumAlias(const std::string&); const char* ColumnName(int); const char* ColumnAlias(int); const char* ColumnTable(int); IBPP::SDT ColumnType(int); int ColumnSubtype(int); int ColumnSize(int); int ColumnScale(int); int Columns(); IBPP::SDT ParameterType(int); int ParameterSubtype(int); int ParameterSize(int); int ParameterScale(int); int Parameters(); void Plan(std::string&); IBPP::Database DatabasePtr() const; IBPP::Transaction TransactionPtr() const; IBPP::IStatement* AddRef(); void Release(); }; class BlobImpl : public IBPP::IBlob { // (((((((( OBJECT INTERNALS )))))))) private: friend class RowImpl; int mRefCount; bool mIdAssigned; ISC_QUAD mId; isc_blob_handle mHandle; bool mWriteMode; DatabaseImpl* mDatabase; // Belongs to this database TransactionImpl* mTransaction; // Belongs to this transaction void Init(); void SetId(ISC_QUAD*); void GetId(ISC_QUAD*); public: void AttachDatabaseImpl(DatabaseImpl*); void DetachDatabaseImpl(); void AttachTransactionImpl(TransactionImpl*); void DetachTransactionImpl(); BlobImpl(const BlobImpl&); BlobImpl(DatabaseImpl*, TransactionImpl* = 0); ~BlobImpl(); // (((((((( OBJECT INTERFACE )))))))) public: void Create(); void Open(); void Close(); void Cancel(); int Read(void*, int size); void Write(const void*, int size); void Info(int* Size, int* Largest, int* Segments); void Save(const std::string& data); void Load(std::string& data); IBPP::Database DatabasePtr() const; IBPP::Transaction TransactionPtr() const; IBPP::IBlob* AddRef(); void Release(); }; class ArrayImpl : public IBPP::IArray { // (((((((( OBJECT INTERNALS )))))))) private: friend class RowImpl; int mRefCount; // Reference counter bool mIdAssigned; ISC_QUAD mId; bool mDescribed; ISC_ARRAY_DESC mDesc; DatabaseImpl* mDatabase; // Database attachée TransactionImpl* mTransaction; // Transaction attachée void* mBuffer; // Buffer for native data int mBufferSize; // Size of this buffer in bytes int mElemCount; // Count of elements in this array int mElemSize; // Size of an element in the buffer void Init(); void SetId(ISC_QUAD*); void GetId(ISC_QUAD*); void ResetId(); void AllocArrayBuffer(); public: void AttachDatabaseImpl(DatabaseImpl*); void DetachDatabaseImpl(); void AttachTransactionImpl(TransactionImpl*); void DetachTransactionImpl(); ArrayImpl(const ArrayImpl&); ArrayImpl(DatabaseImpl*, TransactionImpl* = 0); ~ArrayImpl(); // (((((((( OBJECT INTERFACE )))))))) public: void Describe(const std::string& table, const std::string& column); void ReadTo(IBPP::ADT, void*, int); void WriteFrom(IBPP::ADT, const void*, int); IBPP::SDT ElementType(); int ElementSize(); int ElementScale(); int Dimensions(); void Bounds(int dim, int* low, int* high); void SetBounds(int dim, int low, int high); IBPP::Database DatabasePtr() const; IBPP::Transaction TransactionPtr() const; IBPP::IArray* AddRef(); void Release(); }; // // EventBufferIterator: used in EventsImpl implementation. // template struct EventBufferIterator { It mIt; public: EventBufferIterator& operator++() { mIt += 1 + static_cast(*mIt) + 4; return *this; } bool operator == (const EventBufferIterator& i) const { return i.mIt == mIt; } bool operator != (const EventBufferIterator& i) const { return i.mIt != mIt; } #ifdef __BCPLUSPLUS__ #pragma warn -8027 #endif std::string get_name() const { return std::string(mIt + 1, mIt + 1 + static_cast(*mIt)); } #ifdef __BCPLUSPLUS__ #pragma warn .8027 #endif uint32_t get_count() const { return (*gds.Call()->m_vax_integer) (const_cast(&*(mIt + 1 + static_cast(*mIt))), 4); } // Those container like begin() and end() allow access to the underlying type It begin() { return mIt; } It end() { return mIt + 1 + static_cast(*mIt) + 4; } EventBufferIterator() {} EventBufferIterator(It it) : mIt(it) {} }; class EventsImpl : public IBPP::IEvents { static const size_t MAXEVENTNAMELEN; static void EventHandler(const char*, short, const char*); typedef std::vector ObjRefs; ObjRefs mObjectReferences; typedef std::vector Buffer; Buffer mEventBuffer; Buffer mResultsBuffer; int mRefCount; // Reference counter DatabaseImpl* mDatabase; ISC_LONG mId; // Firebird internal Id of these events bool mQueued; // Has isc_que_events() been called? bool mTrapped; // EventHandled() was called since last que_events() void FireActions(); void Queue(); void Cancel(); EventsImpl& operator=(const EventsImpl&); EventsImpl(const EventsImpl&); public: void AttachDatabaseImpl(DatabaseImpl*); void DetachDatabaseImpl(); EventsImpl(DatabaseImpl* dbi); ~EventsImpl(); // (((((((( OBJECT INTERFACE )))))))) public: void Add(const std::string&, IBPP::EventInterface*); void Drop(const std::string&); void List(std::vector&); void Clear(); // Drop all events void Dispatch(); // Dispatch NON async events IBPP::Database DatabasePtr() const; IBPP::IEvents* AddRef(); void Release(); }; void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt); void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt); void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm); void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm); void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts); void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts); struct consts // See _ibpp.cpp for initializations of these constants { static const double dscales[19]; static const int Dec31_1899; static const int16_t min16; static const int16_t max16; static const int32_t min32; static const int32_t max32; }; } // namespace ibpp_internal #endif // __INTERNAL_IBPP_H__ // // Eof //