Firebird. Use runtime dynamic linking using .dli file instead of static linking against DLL.

git-svn-id: svn://ultimatepp.org/upp/trunk@7837 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
novo 2014-10-30 03:28:28 +00:00
parent 545f00f8de
commit 210ff60a52
6 changed files with 201 additions and 126 deletions

View file

@ -1,4 +1,4 @@
#include "Firebird.h"
#include "firebird.h"
#include <time.h>
NAMESPACE_UPP
@ -498,13 +498,15 @@ void FBVarying::SetValue(const Value& v)
struct FBTimeStamp : public FBValue {
ISC_TIMESTAMP value;
FBTimeStamp(XSQLVAR& v);
FBTimeStamp(XSQLVAR& v, T_FB& dll);
virtual void GetValue(Ref r) const;
virtual void SetValue(const Value& v);
T_FB& dll;
};
FBTimeStamp::FBTimeStamp(XSQLVAR& v) : FBValue(v)
FBTimeStamp::FBTimeStamp(XSQLVAR& v, T_FB& dll) : FBValue(v), dll(dll)
{
v.sqltype = SQL_TIMESTAMP + (v.sqltype & 1);
v.sqldata = reinterpret_cast<ISC_SCHAR*>(&value);
@ -518,7 +520,7 @@ void FBTimeStamp::GetValue(Ref r) const
else {
const LanguageInfo& li = GetLanguageInfo();
struct tm time;
isc_decode_timestamp(&value, &time);
dll.isc_decode_timestamp(&value, &time);
const Time t(time.tm_year + 1900, time.tm_mon + 1, time.tm_mday,
time.tm_hour, time.tm_min, time.tm_sec);
@ -605,19 +607,21 @@ void FBTimeStamp::SetValue(const Value& v)
time.tm_sec = t.second;
time.tm_isdst = -1;
isc_encode_timestamp(&time, &value);
dll.isc_encode_timestamp(&time, &value);
}
struct FBDate : public FBValue {
ISC_DATE value;
FBDate(XSQLVAR& v);
FBDate(XSQLVAR& v, T_FB& dll);
virtual void GetValue(Ref r) const;
virtual void SetValue(const Value& v);
T_FB& dll;
};
FBDate::FBDate(XSQLVAR& v) : FBValue(v)
FBDate::FBDate(XSQLVAR& v, T_FB& dll) : FBValue(v), dll(dll)
{
v.sqltype = SQL_DATE + (v.sqltype & 1);
v.sqldata = reinterpret_cast<ISC_SCHAR*>(&value);
@ -631,7 +635,7 @@ void FBDate::GetValue(Ref r) const
else {
const LanguageInfo& li = GetLanguageInfo();
struct tm time;
isc_decode_sql_date(&value, &time);
dll.isc_decode_sql_date(&value, &time);
const Date d(time.tm_year + 1900, time.tm_mon + 1, time.tm_mday);
@ -716,13 +720,13 @@ void FBDate::SetValue(const Value& v)
time.tm_sec = 0;
time.tm_isdst = -1;
isc_encode_sql_date(&time, &value);
dll.isc_encode_sql_date(&time, &value);
}
struct FBBlob : public FBValue {
mutable ibpp::SegmentBlob value;
FBBlob(const FBSession& s, XSQLVAR& v);
FBBlob(FBSession& s, XSQLVAR& v);
long GetLength() const
{
@ -736,9 +740,9 @@ struct FBBlob : public FBValue {
virtual void SetValue(const Value& v);
};
FBBlob::FBBlob(const FBSession& s, XSQLVAR& v)
FBBlob::FBBlob(FBSession& s, XSQLVAR& v)
: FBValue(v)
, value(s.db, s.tr)
, value(s.db, s.tr, s.dll, s.ib_error)
{
v.sqltype = SQL_BLOB + (v.sqltype & 1);
v.sqldata = reinterpret_cast<ISC_SCHAR*>(&value.getID());
@ -1027,7 +1031,7 @@ FBConnection::FBConnection(FBSession& s)
: executed_(false)
, st(stNone)
, session(s)
, dSQL_(s.db, s.tr)
, dSQL_(s.db, s.tr, s.dll, s.ib_error)
{
}
@ -1087,10 +1091,10 @@ void FBConnection::SetupConverters(ibpp::SQLDataArray& from, Array<FBValue>& to)
break;
case SQL_DATE:
case SQL_TYPE_TIME:
to.Add(new FBTimeStamp(var));
to.Add(new FBTimeStamp(var, session.dll));
break;
case SQL_TYPE_DATE:
to.Add(new FBDate(var));
to.Add(new FBDate(var, session.dll));
break;
case SQL_BLOB:
to.Add(new FBBlob(session, var));
@ -1274,14 +1278,21 @@ SqlSession& FBConnection::GetSession() const
return session;
}
FBSession::FBSession()
FBSession::FBSession(const String& dllName)
: SvcConnected(false)
, DbConnected(false)
, TrStarted(false)
, CursIsClosed(true)
, TrExplicit(false)
, tmpDataArray(1)
, dll(FB())
, ib_error(dll)
, svc(dll, ib_error)
, db(dll, ib_error)
, tr(dll, ib_error)
{
if (!dllName.IsEmpty())
dll.SetLibName(dllName);
}
FBSession::~FBSession()
@ -1303,9 +1314,15 @@ void FBSession::Connect(
const char* host,
const char* user,
const char* pswd,
const String& dllName,
ibpp::network_protocol_t protocol
)
{
if (!dllName.IsEmpty())
dll.SetLibName(dllName);
if (!dll.Load())
throw ibpp::DbExc(dll.GetLibName() + " wasn't found.");
// Service
svc.attach(host, user, pswd, protocol);
SvcConnected = true;
@ -1315,7 +1332,7 @@ void FBSession::Connect(
db.setPassword(pswd);
db.attach(dbname);
DbConnected = true;
dbName = dbname;
DbName = dbname;
// Transaction
tr.setVersion3();
@ -1391,7 +1408,7 @@ Vector<SqlColumnInfo> FBSession::EnumColumns(String /*database*/, String table)
Vector<String> FBSession::EnumDatabases()
{
Vector<String> result;
result.Add(dbName);
result.Add(DbName);
return result;
}
@ -1805,7 +1822,7 @@ void FBSession::Rollback()
void FBSession::CommitRetaining()
{
if (IsTransStarted())
if (TrStarted)
{
tr.commit_retaining();
SetCursorIsClosed(); // By transaction.
@ -1814,7 +1831,7 @@ void FBSession::CommitRetaining()
void FBSession::RollbackRetaining()
{
if (IsTransStarted())
if (TrStarted)
{
tr.rollback_retaining();
SetCursorIsClosed(); // By transaction.
@ -1823,7 +1840,7 @@ void FBSession::RollbackRetaining()
void FBSession::BeginInternal()
{
if (!IsTransStarted())
if (!TrStarted)
{
tr.start(db);
TrStarted = true;
@ -1832,7 +1849,7 @@ void FBSession::BeginInternal()
void FBSession::CommitInternal()
{
if (IsTransStarted())
if (TrStarted)
{
tr.commit();
TrStarted = false;
@ -1842,7 +1859,7 @@ void FBSession::CommitInternal()
void FBSession::RollbackInternal()
{
if (IsTransStarted())
if (TrStarted)
{
tr.rollback();
TrStarted = false;

View file

@ -60,7 +60,7 @@ public:
virtual String Savepoint();
public:
FBSession();
FBSession(const String& dllName = Null);
virtual ~FBSession();
public:
@ -69,6 +69,7 @@ public:
const char* host = NULL,
const char* user = NULL,
const char* pswd = NULL,
const String& dllName = Null, // In case of empty value default dll will be used.
ibpp::network_protocol_t protocol = ibpp::np_local
);
@ -87,7 +88,7 @@ protected:
void RollbackInternal();
// Commit a transaction, and start a new one using the original
// transaction's context
// transactions context
void CommitRetaining();
void RollbackRetaining();
@ -101,7 +102,9 @@ private:
bool CursIsClosed:1;
bool TrExplicit:1;
String dbName;
String DbName;
T_FB& dll;
ibpp::Error ib_error;
ibpp::Service svc;
ibpp::DataBase db;
ibpp::Transaction tr;

View file

@ -3,15 +3,12 @@ description "Firebird/Interbase interface\377";
uses
Sql;
library(WIN32) fbclient_ms.lib;
library(LINUX) fbclient;
file
fb.h,
fb.cpp,
Firebird.h,
Firebird.cpp,
Firebird.dli,
FirebirdSchema.h;
mainconfig

View file

@ -1,5 +1,21 @@
// vi: noexpandtab:tabstop=4
/*
Author: Sergey Sikorskiy (www.sikorskiy.net)
License: BSD
*/
#include "fb.h"
#ifdef PLATFORM_WIN32
#define DLLFILENAME "fbclient.dll"
#define DLLCALL __stdcall
#else
#define DLLFILENAME "fbclient.so"
#endif
#define DLIMODULE FB
#define DLIHEADER <firebird/firebird.dli>
#include <Core/dli_source.h>
// Development-time comments ...
@ -189,24 +205,11 @@
namespace ibpp
{
///////////////////////////////////////////////////////////////////////////
Error ib_error;
inline
void
check(ISC_STATUS rc)
{
if (rc)
{
ib_error.check();
}
}
///////////////////////////////////////////////////////////////////////////
long
Error::getSQLCode()
{
sqlCode_ = isc_sqlcode(status_vector_);
sqlCode_ = dll.isc_sqlcode(status_vector_);
if (sqlCode_ == 999)
{
sqlCode_ = 0;
@ -224,18 +227,18 @@ namespace ibpp
#if 0
ISC_STATUS* pVector = status_vector_;
isc_interprete(msg_, &pVector);
dll.isc_interprete(msg_, &pVector);
errStr += msg_;
while (isc_interprete(msg_, &pVector))
while (dll.isc_interprete(msg_, &pVector))
{
errStr += "; ";
errStr += msg_;
}
#else
const ISC_STATUS* pVector = status_vector_;
fb_interpret(msg_, sizeof(msg_), &pVector);
dll.fb_interpret(msg_, sizeof(msg_), &pVector);
errStr += msg_;
while (fb_interpret(msg_, sizeof(msg_), &pVector))
while (dll.fb_interpret(msg_, sizeof(msg_), &pVector))
{
errStr += "; ";
errStr += msg_;
@ -338,8 +341,10 @@ namespace ibpp
}
///////////////////////////////////////////////////////////////////////////
DataBase::DataBase() :
handle_(NULL)
DataBase::DataBase(T_FB& dll, Error& ib_error)
: handle_(NULL)
, dll(dll)
, ib_error(ib_error)
{
}
@ -347,7 +352,7 @@ namespace ibpp
DataBase::attach(const char* name)
{
handle_ = NULL;
check(isc_attach_database(
ib_error.check(dll.isc_attach_database(
ib_error.getErrorVector(),
strlen(name),
const_cast<char*>(name),
@ -362,7 +367,7 @@ namespace ibpp
{
if (handle_ != 0)
{
check(isc_detach_database(
ib_error.check(dll.isc_detach_database(
ib_error.getErrorVector(),
//const_cast<void**>(&handle_)
&handle_
@ -373,7 +378,7 @@ namespace ibpp
void
DataBase::drop()
{
check(isc_drop_database(
ib_error.check(dll.isc_drop_database(
ib_error.getErrorVector(),
//const_cast<void**>(&handle_)
&handle_
@ -387,7 +392,7 @@ namespace ibpp
ASSERT(handle_ == 0);
isc_tr_handle tr_handle = NULL;
check(isc_dsql_execute_immediate(
ib_error.check(dll.isc_dsql_execute_immediate(
ib_error.getErrorVector(),
&handle_,
&tr_handle,
@ -397,7 +402,7 @@ namespace ibpp
NULL // inDataArray_.getBuffer()
));
check(isc_detach_database(
ib_error.check(dll.isc_detach_database(
ib_error.getErrorVector(),
//static_cast<void**>(&handle_)
&handle_
@ -468,7 +473,7 @@ namespace ibpp
typedef ISC_VERSION_CALLBACK cb_type;
#endif
check(isc_version(
ib_error.check(dll.isc_version(
&handle_,
(cb_type)version_callback,
this
@ -476,8 +481,10 @@ namespace ibpp
}
///////////////////////////////////////////////////////////////////////////
Transaction::Transaction() :
handle_(0L)
Transaction::Transaction(T_FB& dll, Error& ib_error)
: handle_(0L)
, dll(dll)
, ib_error(ib_error)
{
}
@ -490,7 +497,7 @@ namespace ibpp
// isc_start_transaction () in its place. A default set of attributes is automatically assigned to
// such transactions.
check(isc_start_transaction(
ib_error.check(dll.isc_start_transaction(
ib_error.getErrorVector(),
&handle_,
1, // Number of database handles passed in this call
@ -513,7 +520,7 @@ namespace ibpp
void
Transaction::commit()
{
check(isc_commit_transaction(
ib_error.check(dll.isc_commit_transaction(
ib_error.getErrorVector(),
&handle_
));
@ -522,7 +529,7 @@ namespace ibpp
void
Transaction::commit_retaining()
{
check(isc_commit_retaining(
ib_error.check(dll.isc_commit_retaining(
ib_error.getErrorVector(),
&handle_
));
@ -531,7 +538,7 @@ namespace ibpp
void
Transaction::rollback()
{
check(isc_rollback_transaction(
ib_error.check(dll.isc_rollback_transaction(
ib_error.getErrorVector(),
&handle_
));
@ -543,7 +550,7 @@ namespace ibpp
// isc_rollback_retaining () should be used with caution because the error
// that caused the rollback may be in the transactions context. In this case, until the context
// is released the error will continue.
check(isc_rollback_retaining(
ib_error.check(dll.isc_rollback_retaining(
ib_error.getErrorVector(),
&handle_
));
@ -552,7 +559,7 @@ namespace ibpp
void
Transaction::prepare()
{
check(isc_prepare_transaction(
ib_error.check(dll.isc_prepare_transaction(
ib_error.getErrorVector(),
&handle_
));
@ -648,12 +655,14 @@ namespace ibpp
}
///////////////////////////////////////////////////////////////////////////
DynamicSQL::DynamicSQL(const DataBase& db, const Transaction& tr)
: dialect_(3)
, pDBHandle_(db.getHandleP())
, pTRHandle_(tr.getHandleP())
, handle_(NULL)
, all_data_fetched_(false)
DynamicSQL::DynamicSQL(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error)
: dialect_(3)
, pDBHandle_(db.getHandleP())
, pTRHandle_(tr.getHandleP())
, dll(dll)
, ib_error(ib_error)
, handle_(NULL)
, all_data_fetched_(false)
{
allocate_stmt2();
}
@ -673,7 +682,7 @@ namespace ibpp
void
DynamicSQL::execute_immediate(const String& stmt)
{
check(isc_dsql_execute_immediate(
ib_error.check(dll.isc_dsql_execute_immediate(
ib_error.getErrorVector(),
pDBHandle_,
pTRHandle_,
@ -689,7 +698,7 @@ namespace ibpp
void
DynamicSQL::execute_immediate_data(const String& stmt)
{
check(isc_dsql_exec_immed2(
ib_error.check(dll.isc_dsql_exec_immed2(
ib_error.getErrorVector(),
pDBHandle_,
pTRHandle_,
@ -708,7 +717,7 @@ namespace ibpp
ASSERT(*pDBHandle_ == 0);
ASSERT(*pTRHandle_ == 0);
check(isc_dsql_execute_immediate(
ib_error.check(dll.isc_dsql_execute_immediate(
ib_error.getErrorVector(),
pDBHandle_,
pTRHandle_,
@ -724,7 +733,7 @@ namespace ibpp
void
DynamicSQL::prepare(const String& stmt, const SQLDataArray& define_da)
{
check(isc_dsql_prepare(
ib_error.check(dll.isc_dsql_prepare(
ib_error.getErrorVector(),
pTRHandle_,
&handle_,
@ -738,7 +747,7 @@ namespace ibpp
void
DynamicSQL::execute()
{
check(isc_dsql_execute(
ib_error.check(dll.isc_dsql_execute(
ib_error.getErrorVector(),
pTRHandle_,
&handle_,
@ -753,7 +762,7 @@ namespace ibpp
void
DynamicSQL::execute2()
{
check(isc_dsql_execute2(
ib_error.check(dll.isc_dsql_execute2(
ib_error.getErrorVector(),
pTRHandle_,
&handle_,
@ -769,7 +778,7 @@ namespace ibpp
void
DynamicSQL::describe_bind(const SQLDataArray& da)
{
check(isc_dsql_describe_bind(
ib_error.check(dll.isc_dsql_describe_bind(
ib_error.getErrorVector(),
&handle_,
// Indicates the version of the extended SQL descriptor area (XSQLDA)
@ -782,7 +791,7 @@ namespace ibpp
void
DynamicSQL::describe_define(const SQLDataArray& da)
{
check(isc_dsql_describe(
ib_error.check(dll.isc_dsql_describe(
ib_error.getErrorVector(),
&handle_,
// Indicates the version of the extended SQL descriptor area (XSQLDA)
@ -795,7 +804,7 @@ namespace ibpp
void
DynamicSQL::setCursorName(const char* name)
{
check(isc_dsql_set_cursor_name(
ib_error.check(dll.isc_dsql_set_cursor_name(
ib_error.getErrorVector(),
&handle_,
const_cast<char*>(name),
@ -808,7 +817,7 @@ namespace ibpp
{
if (!all_data_fetched_)
{
int fetch_stat = isc_dsql_fetch(
int fetch_stat = dll.isc_dsql_fetch(
ib_error.getErrorVector(),
&handle_,
// Indicates the version of the extended SQL descriptor area (XSQLDA)
@ -842,7 +851,7 @@ namespace ibpp
char res_buffer[8];
int st_type = 0;
check(isc_dsql_sql_info(
ib_error.check(dll.isc_dsql_sql_info(
ib_error.getErrorVector(),
&handle_,
sizeof(type_item),
@ -854,8 +863,8 @@ namespace ibpp
if (res_buffer[0] == isc_info_sql_stmt_type)
{
short length;
length = static_cast<short>(isc_portable_integer(reinterpret_cast<unsigned char*>(res_buffer + 1), 2));
st_type = static_cast<int>(isc_portable_integer(reinterpret_cast<unsigned char*>(res_buffer + 3), length));
length = static_cast<short>(dll.isc_portable_integer(reinterpret_cast<unsigned char*>(res_buffer + 1), 2));
st_type = static_cast<int>(dll.isc_portable_integer(reinterpret_cast<unsigned char*>(res_buffer + 3), length));
}
return st_type;
@ -871,7 +880,7 @@ namespace ibpp
if (handle_ == 0)
{
check(isc_dsql_allocate_statement(
ib_error.check(dll.isc_dsql_allocate_statement(
ib_error.getErrorVector(),
pDBHandle_,
&handle_
@ -893,7 +902,7 @@ namespace ibpp
if (handle_ == 0)
{
check(isc_dsql_alloc_statement2(
ib_error.check(dll.isc_dsql_alloc_statement2(
ib_error.getErrorVector(),
pDBHandle_,
&handle_
@ -908,7 +917,7 @@ namespace ibpp
void
DynamicSQL::close_cursor()
{
check(isc_dsql_free_statement(
ib_error.check(dll.isc_dsql_free_statement(
ib_error.getErrorVector(),
&handle_,
DSQL_close
@ -919,7 +928,7 @@ namespace ibpp
void
DynamicSQL::drop_statement()
{
check(isc_dsql_free_statement(
ib_error.check(dll.isc_dsql_free_statement(
ib_error.getErrorVector(),
&handle_,
DSQL_drop
@ -1147,7 +1156,7 @@ namespace ibpp
{
char clm_global_name[256];
check(isc_blob_lookup_desc(
ib_error.check(dll.isc_blob_lookup_desc(
ib_error.getErrorVector(),
blob.pDBHandle_,
blob.pTRHandle_,
@ -1197,11 +1206,13 @@ namespace ibpp
{
}
SegmentBlob::SegmentBlob(const DataBase& db, const Transaction& tr) :
pDBHandle_(db.getHandleP()),
pTRHandle_(tr.getHandleP()),
isOpen_(false),
hasInfo_(false)
SegmentBlob::SegmentBlob(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error) :
pDBHandle_(db.getHandleP()),
pTRHandle_(tr.getHandleP()),
dll(dll),
ib_error(ib_error),
isOpen_(false),
hasInfo_(false)
{
handle_ = NULL;
@ -1223,7 +1234,7 @@ namespace ibpp
{
handle_ = NULL;
check(isc_open_blob(
ib_error.check(dll.isc_open_blob(
ib_error.getErrorVector(),
pDBHandle_,
pTRHandle_,
@ -1237,7 +1248,7 @@ namespace ibpp
{
handle_ = NULL;
check(isc_open_blob2(
ib_error.check(dll.isc_open_blob2(
ib_error.getErrorVector(),
pDBHandle_,
pTRHandle_,
@ -1288,7 +1299,7 @@ namespace ibpp
id_.gds_quad_low = 0;
id_.gds_quad_high = 0;
check(isc_create_blob(
ib_error.check(dll.isc_create_blob(
ib_error.getErrorVector(),
pDBHandle_,
pTRHandle_,
@ -1304,7 +1315,7 @@ namespace ibpp
id_.gds_quad_low = 0;
id_.gds_quad_high = 0;
check(isc_create_blob2(
ib_error.check(dll.isc_create_blob2(
ib_error.getErrorVector(),
pDBHandle_,
pTRHandle_,
@ -1329,7 +1340,7 @@ namespace ibpp
if (isOpen_)
{
ASSERT(handle_);
check(isc_close_blob(
ib_error.check(dll.isc_close_blob(
ib_error.getErrorVector(),
&handle_
));
@ -1351,7 +1362,7 @@ namespace ibpp
open();
ASSERT(handle_);
stat_ = isc_get_segment(
stat_ = dll.isc_get_segment(
ib_error.getErrorVector(),
&handle_,
&actualSegLen,
@ -1377,7 +1388,7 @@ namespace ibpp
open();
ASSERT(handle_);
check(isc_put_segment(
ib_error.check(dll.isc_put_segment(
ib_error.getErrorVector(),
&handle_,
seg_length,
@ -1409,7 +1420,7 @@ namespace ibpp
SegmentBlob::cancel()
{
ASSERT(handle_);
check(isc_cancel_blob(
ib_error.check(dll.isc_cancel_blob(
ib_error.getErrorVector(),
&handle_
));
@ -1434,7 +1445,7 @@ namespace ibpp
open();
ASSERT(handle_);
check(isc_blob_info(
ib_error.check(dll.isc_blob_info(
ib_error.getErrorVector(),
&handle_,
sizeof(blob_items),/* Length of item-list buffer. */
@ -1449,23 +1460,23 @@ namespace ibpp
char item = *p++;
short length = (short)isc_vax_integer(p, 2);
short length = (short)dll.isc_vax_integer(p, 2);
p += 2;
switch (item)
{
case isc_info_blob_total_length:
info_.lenght_ = isc_vax_integer(p, length);
info_.lenght_ = dll.isc_vax_integer(p, length);
break;
case isc_info_blob_max_segment:
info_.maxSegments_ = isc_vax_integer(p, length);
info_.maxSegments_ = dll.isc_vax_integer(p, length);
break;
case isc_info_blob_num_segments:
info_.numSegments_ = isc_vax_integer(p, length);
info_.numSegments_ = dll.isc_vax_integer(p, length);
break;
case isc_info_blob_type:
info_.type_segmented = (isc_vax_integer(p, length) == 0);
info_.type_segmented = (dll.isc_vax_integer(p, length) == 0);
break;
case isc_info_truncated:
// handle error
@ -1666,7 +1677,7 @@ namespace ibpp
paramBuff.addCluster(isc_spb_password, pswd);
handle_ = 0L;
check(isc_service_attach(
ib_error.check(dll.isc_service_attach(
ib_error.getErrorVector(),
service_host.GetCount(),
service_host,
@ -1679,7 +1690,7 @@ namespace ibpp
void
Service::detach()
{
check(isc_service_detach(
ib_error.check(dll.isc_service_detach(
ib_error.getErrorVector(),
&handle_
));
@ -1688,7 +1699,7 @@ namespace ibpp
void
Service::executeCommand(const spb& pb)
{
check(isc_service_start(
ib_error.check(dll.isc_service_start(
ib_error.getErrorVector(),
&handle_,
NULL,
@ -1706,7 +1717,7 @@ namespace ibpp
flags_buff.addParam(isc_spb_current_version);
flags_buff.addCluster(isc_info_svc_timeout, 60);
check(isc_service_query(
ib_error.check(dll.isc_service_query(
ib_error.getErrorVector(),
&handle_,
NULL,
@ -1813,7 +1824,7 @@ namespace ibpp
unsigned long result;
// p += sizeof(unsigned short);
result = (unsigned long)isc_portable_integer((unsigned char*)p, sizeof(result));
result = (unsigned long)svc_ptr_->get_dll().isc_portable_integer((unsigned char*)p, sizeof(result));
p += sizeof(unsigned long);
return result;
}
@ -1824,7 +1835,7 @@ namespace ibpp
unsigned short result;
// p += sizeof(unsigned short);
result = (unsigned short)isc_portable_integer((unsigned char*)p, sizeof(result));
result = (unsigned short)svc_ptr_->get_dll().isc_portable_integer((unsigned char*)p, sizeof(result));
p += sizeof(unsigned short);
return result;
}
@ -1835,7 +1846,7 @@ namespace ibpp
String result;
size_t str_length;
str_length = (unsigned short)isc_portable_integer((unsigned char*)p, sizeof(unsigned short));
str_length = (unsigned short)svc_ptr_->get_dll().isc_portable_integer((unsigned char*)p, sizeof(unsigned short));
p += sizeof(unsigned short);
result = String(p, str_length);
p += str_length;

View file

@ -1,8 +1,24 @@
// vi: noexpandtab:tabstop=4
#ifndef _firebird_fb_h_
#define _firebird_fb_h_
/*
Author: Sergey Sikorskiy (www.sikorskiy.net)
License: BSD
*/
#include <Sql/Sql.h>
#include <ibase.h>
#include "lib/ibase.h"
#ifdef PLATFORM_WIN32
#define DLLFILENAME "fbclient.dll"
#define DLLCALL __stdcall
#else
#define DLLFILENAME "fbclient.so"
#endif
#define DLIMODULE FB
#define DLIHEADER <firebird/firebird.dli>
#include <Core/dli_header.h>
namespace ibpp
{
@ -31,6 +47,8 @@ namespace ibpp
class Error
{
public:
Error(T_FB& dll) : dll(dll) {}
ISC_STATUS* getErrorVector()
{
return status_vector_;
@ -45,15 +63,22 @@ namespace ibpp
{
return status_vector_[1];
}
void check(ISC_STATUS rc)
{
if (rc)
check();
}
protected:
T_FB& dll;
private:
ISC_STATUS status_vector_[20];
long sqlCode_;
ISC_STATUS status_vector_[20];
char msg_[1024];
};
extern Error ib_error;
class dpb
{
public:
@ -129,7 +154,7 @@ namespace ibpp
class DataBase
{
public:
DataBase();
DataBase(T_FB& dll, Error& ib_error);
public:
isc_db_handle* getHandleP() const
@ -281,6 +306,8 @@ namespace ibpp
private:
mutable isc_db_handle handle_;
DBParamBuff paramBuff_;
T_FB& dll;
Error& ib_error;
public:
// Because I cannot make a friend function ...
@ -291,7 +318,7 @@ namespace ibpp
class Transaction
{
public:
Transaction();
Transaction(T_FB& dll, Error& ib_error);
public:
isc_tr_handle* getHandleP() const
@ -436,6 +463,8 @@ namespace ibpp
private:
mutable isc_tr_handle handle_;
dpb paramBuff_;
T_FB& dll;
Error& ib_error;
};
class SQLDataArray
@ -479,7 +508,7 @@ namespace ibpp
class DynamicSQL
{
public:
DynamicSQL(const DataBase& db, const Transaction& tr);
DynamicSQL(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error);
~DynamicSQL();
public:
@ -552,6 +581,9 @@ namespace ibpp
isc_db_handle* pDBHandle_;
isc_tr_handle* pTRHandle_;
T_FB& dll;
Error& ib_error;
isc_stmt_handle handle_; // It is a pointer, actualy.
SQLDataArray inDataArray_;
@ -572,6 +604,8 @@ namespace ibpp
class BlobDescr
{
public:
BlobDescr(T_FB& dll, Error& ib_error) : dll(dll), ib_error(ib_error) {}
// Determines the subtype, character set, and segment size of a SegmentBlob, given a table name
// and SegmentBlob column name.
void get(
@ -588,6 +622,8 @@ namespace ibpp
protected:
private:
ISC_BLOB_DESC blobDescr_;
T_FB& dll;
Error& ib_error;
};
class SegmentBlob
@ -624,7 +660,7 @@ namespace ibpp
};
public:
SegmentBlob(const DataBase& db, const Transaction& tr);
SegmentBlob(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error);
~SegmentBlob();
public:
@ -678,6 +714,9 @@ namespace ibpp
isc_tr_handle* pTRHandle_;
isc_blob_handle handle_; // It is a pointer, actualy.
T_FB& dll;
Error& ib_error;
GDS_QUAD id_; // SegmentBlob ID put into out_sqlda by isc_dsql_fetch()
int stat_;
bool isOpen_;
@ -741,6 +780,8 @@ namespace ibpp
class Service
{
public:
Service(T_FB& dll, Error& ib_error) : dll(dll), ib_error(ib_error) {}
void attach(
const char* host = NULL,
const char* user = NULL,
@ -754,8 +795,13 @@ namespace ibpp
void query(const spb& request, const spb& result);
T_FB& get_dll() { return dll; }
Error& get_ib_error() { return ib_error; }
private:
isc_svc_handle handle_;
T_FB& dll;
Error& ib_error;
};
class user_info : Moveable<user_info>

View file

@ -1,4 +1,4 @@
#include "Firebird/Firebird.h"
#include "firebird/firebird.h"
using namespace Upp;
@ -1032,14 +1032,15 @@ public:
CONSOLE_APP_MAIN
{
const Vector<String>& cmd_line = CommandLine();
if (cmd_line.GetCount() > 0 && FileExists(cmd_line[0]))
if (cmd_line.GetCount() > 1 && FileExists(cmd_line[0]) && FileExists(cmd_line[1]))
{
FBSession s;
s.Connect(
cmd_line[0],
cmd_line[1],
NULL,
"SYSDBA",
"masterkey"
"masterkey",
cmd_line[0]
);
#if 0