///////////////////////////////////////////////////////////////////////////////
//
// File : $Id$
// Subject : IBPP internal declarations
//
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2000-2007 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 <windows.h>
#endif
#include <limits>
#include <string>
#include <vector>
#include <set>
#include <sstream>
#include <cstdarg>
#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
//lint -e{1511} member hides non-virtual member
std::ostream& operator<< (const char* p)
{ static_cast<std::stringstream&>(*this)<< p; return *this; }
//lint -e{1511} member hides non-virtual member
std::ostream& operator<< (const std::string& p)
{ static_cast<std::stringstream&>(*this)<< p; return *this; }
//lint -e{1529} not first checking for assignement to this
//lint -e{1539} member not assigned by assigment operator
DebugStream& operator=(const DebugStream&) {return *this;}
DebugStream(const DebugStream&) : std::stringstream() {}
DebugStream() {}
};
std::ostream& operator<< (std::ostream& a, flush_debug_stream_type);
#else
struct DebugStream
{
template<class T> 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 *);
typedef int ISC_EXPORT proto_shutdown(unsigned int, const int);
class DriverImpl; // Forward declaration
//
// Service Parameter Block (used to define a service)
//
class SPB
{
static const int BUFFERINCR;
DriverImpl* mDriver;
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(DriverImpl* drv) : mDriver(drv), mBuffer(0), mSize(0), mAlloc(0) { }
~SPB();
};
//
// Database Parameter Block (used to define a database)
//
class DPB
{
static const int BUFFERINCR;
DriverImpl* mDriver;
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(DriverImpl* drv) : mDriver(drv), mBuffer(0), mSize(0), mAlloc(0) { }
~DPB();
};
//
// 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();
};
//
// Used to receive (and process) a results buffer in various API calls
//
class RB
{
DriverImpl* mDriver;
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(DriverImpl*);
RB(DriverImpl*, int Size);
~RB();
};
//
// Used to receive status info from API calls
//
class IBS
{
DriverImpl* mDriver;
mutable ISC_STATUS mVector[20];
mutable std::string mMessage;
public:
//lint -e{1536} exposing low access member: this is intended
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&); // Copy Constructor
IBS(DriverImpl*);
~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();
ExceptionBase(const ExceptionBase& copied);
ExceptionBase& operator=(const ExceptionBase& copied);
ExceptionBase(const std::string& context, const char* message = 0, ...);
virtual ~ExceptionBase();
// (((((((( OBJECT INTERFACE ))))))))
virtual const char* Origin() const;
virtual const char* ErrorMessage() const;
virtual const char* what() const;
};
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();
LogicExceptionImpl(const LogicExceptionImpl& copied);
LogicExceptionImpl& operator=(const LogicExceptionImpl& copied);
LogicExceptionImpl(const std::string& context, const char* message = 0, ...);
virtual ~LogicExceptionImpl() throw ();
// (((((((( OBJECT INTERFACE ))))))))
//
// The object public interface is partly implemented by inheriting from
// the ExceptionBase class.
public:
virtual const char* Origin() const;
virtual const char* ErrorMessage() const;
virtual const char* what() const;
};
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();
SQLExceptionImpl(const SQLExceptionImpl& copied);
SQLExceptionImpl& operator=(const SQLExceptionImpl& copied);
SQLExceptionImpl(const IBS& status, const std::string& context,
const char* message = 0, ...);
virtual ~SQLExceptionImpl() throw ();
// (((((((( OBJECT INTERFACE ))))))))
//
// The object public interface is partly implemented by inheriting from
// the ExceptionBase class.
public:
virtual const char* Origin() const;
virtual const char* ErrorMessage() const;
virtual const char* what() const;
virtual int SqlCode() const;
virtual int EngineCode() const;
};
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();
WrongTypeImpl(const WrongTypeImpl& copied);
WrongTypeImpl& operator=(const WrongTypeImpl& copied);
WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType,
const char* message = 0, ...);
virtual ~WrongTypeImpl() throw ();
// (((((((( OBJECT INTERFACE ))))))))
//
// The object public interface is partly implemented by inheriting from
// the ExceptionBase class.
public:
virtual const char* Origin() const;
virtual const char* ErrorMessage() const;
virtual const char* what() const;
};
class DriverImpl : public IBPP::IDriver
{
// (((((((( OBJECT INTERNALS ))))))))
private:
int mRefCount; // Reference counter
std::string mPaths; // Optional paths which where used to load the driver
bool mLoaded; // Driver loaded?
std::set<IBPP::IInterface*> mInterfaces;
#ifdef IBPP_WINDOWS
HMODULE mHandle; // The GDS32.DLL HMODULE
std::string mSearchPaths; // Optional additional search paths
#endif
public:
int mGDSVersion; // Version of the GDS32.DLL (50 for 5.0, 60 for 6.0)
// 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;
proto_shutdown* m_shutdown;
const DriverImpl* operator->() const
{
return mLoaded ? this :
throw LogicExceptionImpl("Driver", "Driver instance has been unloaded"), this;
}
bool EmbeddedShutdown(unsigned int timeout, const int reason);
void Detach(IBPP::IInterface*);
DriverImpl();
~DriverImpl();
// (((((((( OBJECT INTERFACE ))))))))
public:
void Load(const std::string& paths);
void Load() { Load(""); }
bool Loaded() const { return mLoaded; }
void Unload();
void GetVersion(std::string& version);
IBPP::Service ServiceFactory(const std::string& ServerName,
const std::string& UserName, const std::string& UserPassword);
IBPP::Database DatabaseFactory(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);
IBPP::Database DatabaseFactory(const std::string& ServerName,
const std::string& DatabaseName, const std::string& UserName,
const std::string& UserPassword)
{ return DatabaseFactory(ServerName, DatabaseName, UserName, UserPassword, "", "", ""); }
IBPP::Transaction TransactionFactory(IBPP::Database db, IBPP::TAM am = IBPP::amWrite,
IBPP::TIL il = IBPP::ilConcurrency, IBPP::TLR lr = IBPP::lrWait,
IBPP::TFF flags = IBPP::TFF(0));
IBPP::Statement StatementFactory(IBPP::Database db, IBPP::Transaction tr,
const std::string& sql);
IBPP::Statement StatementFactory(IBPP::Database db, IBPP::Transaction tr)
{ return StatementFactory(db, tr, ""); }
IBPP::Blob BlobFactory(IBPP::Database db, IBPP::Transaction tr);
IBPP::Array ArrayFactory(IBPP::Database db, IBPP::Transaction tr);
IBPP::Events EventsFactory(IBPP::Database db);
IBPP::IDriver* AddRef();
void Release();
};
class ServiceImpl : public IBPP::IService
{
// (((((((( OBJECT INTERNALS ))))))))
private:
int mRefCount; // Reference counter
DriverImpl* mDriver; // Driver
isc_svc_handle mHandle; // InterBase API Service Handle
std::string mServerName; // Server name
std::string mUserName; // User name
std::string mUserPassword; // User password
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(DriverImpl* drv, 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<IBPP::User>&);
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::Driver DriverPtr() const { return mDriver; }
IBPP::IService* AddRef();
void Release();
};
class DatabaseImpl : public IBPP::IDatabase
{
// (((((((( OBJECT INTERNALS ))))))))
int mRefCount; // Reference counter
DriverImpl* mDriver; // Driver
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<TransactionImpl*> mTransactions;// Table of Transaction*
std::vector<StatementImpl*> mStatements;// Table of Statement*
std::vector<BlobImpl*> mBlobs; // Table of Blob*
std::vector<ArrayImpl*> mArrays; // Table of Array*
std::vector<EventsImpl*> mEvents; // Table of Events*
public:
//lint -e{1536} exposing low access member: this is intended
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(DriverImpl*, 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, bool* ReadOnly = 0);
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<std::string>& 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::Driver DriverPtr() const { return mDriver; }
IBPP::IDatabase* AddRef();
void Release();
};
class TransactionImpl : public IBPP::ITransaction
{
// (((((((( OBJECT INTERNALS ))))))))
private:
int mRefCount; // Reference counter
DriverImpl* mDriver; // Driver
isc_tr_handle mHandle; // Transaction InterBase
std::vector<DatabaseImpl*> mDatabases; // Tableau de IDatabase*
std::vector<StatementImpl*> mStatements; // Tableau de IStatement*
std::vector<BlobImpl*> mBlobs; // Tableau de IBlob*
std::vector<ArrayImpl*> mArrays; // Tableau de Array*
std::vector<TPB*> mTPBs; // Tableau de TPB
void Init(); // A usage exclusif des constructeurs
public:
//lint -e{1536} exposing low access member: this is intended
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(DriverImpl*, 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::Driver DriverPtr() const { return mDriver; }
IBPP::ITransaction* AddRef();
void Release();
};
class RowImpl /* : public IBPP::IRow*/
{
// (((((((( OBJECT INTERNALS ))))))))
private:
int mRefCount; // Reference counter
DriverImpl* mDriver; // Driver
XSQLDA* mDescrArea; // XSQLDA descriptor itself
std::vector<double> mNumerics; // Temporary storage for Numerics
std::vector<float> mFloats; // Temporary storage for Floats
std::vector<int64_t> mInt64s; // Temporary storage for 64 bits
std::vector<int32_t> mInt32s; // Temporary storage for 32 bits
std::vector<int16_t> mInt16s; // Temporary storage for 16 bits
std::vector<char> mBools; // Temporary storage for Bools
std::vector<std::string> mStrings; // Temporary storage for Strings
std::vector<bool> 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(DriverImpl*, int dialect, int size, DatabaseImpl* db, TransactionImpl* tr);
~RowImpl();
// (((((((( OBJECT INTERFACE ))))))))
public:
void SetNull(int);
void Set(int, bool);
void Set(int, const void*, int); // byte buffers
void Set(int, const std::string&);
void Set(int, int16_t);
void Set(int, int);
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, void*, int&); // byte buffers
bool Get(int, std::string&);
bool Get(int, int16_t&);
bool Get(int, int&);
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&, void*, int&); // byte buffers
bool Get(const std::string&, std::string&);
bool Get(const std::string&, int16_t&);
bool Get(const std::string&, int&);
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::Driver DriverPtr() const { return mDriver; }
//IBPP::IRow* Clone();
void AddRef();
void Release();
};
class StatementImpl : public IBPP::IStatement
{
// (((((((( OBJECT INTERNALS ))))))))
private:
friend class TransactionImpl;
int mRefCount; // Reference counter
DriverImpl* mDriver; // Driver
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(DriverImpl*, 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 void*, int); // byte buffers
void Set(int, const char*); // pointer to c-string
void Set(int, const std::string&);
void Set(int, int16_t);
void Set(int, int);
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, void*, int&); // byte buffers
bool Get(int, std::string&);
bool Get(int, int16_t&);
bool Get(int, int&);
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&, void*, int&); // byte buffers
bool Get(const std::string&, std::string&);
bool Get(const std::string&, int16_t&);
bool Get(const std::string&, int&);
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&);
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::Driver DriverPtr() const { return mDriver; }
IBPP::IStatement* AddRef();
void Release();
};
class BlobImpl : public IBPP::IBlob
{
// (((((((( OBJECT INTERNALS ))))))))
private:
friend class RowImpl;
int mRefCount;
DriverImpl* mDriver; // Driver
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(DriverImpl*, 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::Driver DriverPtr() const { return mDriver; }
IBPP::IBlob* AddRef();
void Release();
};
class ArrayImpl : public IBPP::IArray
{
// (((((((( OBJECT INTERNALS ))))))))
private:
friend class RowImpl;
int mRefCount; // Reference counter
DriverImpl* mDriver; // Driver
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(DriverImpl*, 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::Driver DriverPtr() const { return mDriver; }
IBPP::IArray* AddRef();
void Release();
};
//
// EventBufferIterator: used in EventsImpl implementation.
//
template<class It>
struct EventBufferIterator
{
DriverImpl* mDriver;
It mIt;
public:
EventBufferIterator& operator++()
{ mIt += 1 + static_cast<int>(*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<int32_t>(*mIt));
}
#ifdef __BCPLUSPLUS__
#pragma warn .8027
#endif
uint32_t get_count() const
{
return (mDriver->m_vax_integer)
(const_cast<char*>(&*(mIt + 1 + static_cast<int>(*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<int>(*mIt) + 4; }
EventBufferIterator(DriverImpl* drv) : mDriver(drv) {}
EventBufferIterator(DriverImpl* drv, It it) : mDriver(drv), mIt(it) {}
};
class EventsImpl : public IBPP::IEvents
{
static const size_t MAXEVENTNAMELEN;
static void EventHandler(const char*, short, const char*);
typedef std::vector<IBPP::EventInterface*> ObjRefs;
ObjRefs mObjectReferences;
typedef std::vector<char> Buffer;
Buffer mEventBuffer;
Buffer mResultsBuffer;
int mRefCount; // Reference counter
DriverImpl* mDriver; // Driver
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(DriverImpl*, DatabaseImpl* dbi);
~EventsImpl();
// (((((((( OBJECT INTERFACE ))))))))
public:
void Add(const std::string&, IBPP::EventInterface*);
void Drop(const std::string&);
void List(std::vector<std::string>&);
void Clear(); // Drop all events
void Dispatch(); // Dispatch NON async events
IBPP::Database DatabasePtr() const;
IBPP::Driver DriverPtr() const { return mDriver; }
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);
std::string escape(const std::string&, char);
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
//