X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/8c6fa3fbaccc22127280bf77a48fab5a3ee0716e..46b0747592074017ff0ea4b33d4a7194235886e5:/libs/ibpp/_ibpp.h diff --git a/libs/ibpp/_ibpp.h b/libs/ibpp/_ibpp.h new file mode 100644 index 00000000..27d368af --- /dev/null +++ b/libs/ibpp/_ibpp.h @@ -0,0 +1,1414 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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 "stg/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 +//