8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:00:38 +01:00

UDR C++ interface and examples improvements.

This commit is contained in:
asfernandes 2013-06-06 16:05:02 +00:00
parent f3dc865cbf
commit fc9b47b63d
3 changed files with 242 additions and 368 deletions

View File

@ -194,10 +194,15 @@ create function wait_event (
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(wait_event)
FB_UDR_EXECUTE_MESSAGE_FUNCTION(
FB_MESSAGE(InMessage,
(FB_VARCHAR(31 * 4), name)
,
(FB_INTEGER, result))
);
FB_MESSAGE(OutMessage,
(FB_INTEGER, result)
);
FB_UDR_EXECUTE_FUNCTION
{
char* s = new char[in->name.length + 1];
memcpy(s, in->name.str, in->name.length);
@ -213,11 +218,11 @@ FB_UDR_BEGIN_FUNCTION(wait_event)
isc_db_handle dbHandle = getIscDbHandle(context);
ISC_ULONG counter = 0;
StatusException::check(isc_wait_for_event(statusVector, &dbHandle, eveLen, eveBuffer, eveResult),
statusVector);
StatusException::checkStatus(isc_wait_for_event(
statusVector, &dbHandle, eveLen, eveBuffer, eveResult), statusVector);
isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
StatusException::check(isc_wait_for_event(statusVector, &dbHandle, eveLen, eveBuffer, eveResult),
statusVector);
StatusException::checkStatus(isc_wait_for_event(
statusVector, &dbHandle, eveLen, eveBuffer, eveResult), statusVector);
isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
isc_free((char*) eveBuffer);
@ -239,15 +244,17 @@ create function sum_args (
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(sum_args)
FB_UDR_INITIALIZE
// Without InMessage/OutMessage definitions, messages will be byte-based.
FB_UDR_CONSTRUCTOR
// , inCount(0)
{
// Get input metadata.
AutoRelease<IMessageMetadata> inMetadata(metadata->getInputMetadata(status));
StatusException::check(status->get());
AutoRelease<IMessageMetadata> inMetadata(StatusException::check(status,
metadata->getInputMetadata(status)));
// Get count of input parameters.
inCount = inMetadata->getCount(status);
StatusException::check(status->get());
inCount = StatusException::check(status, inMetadata->getCount(status));
inNullOffsets.reset(new unsigned[inCount]);
inOffsets.reset(new unsigned[inCount]);
@ -255,37 +262,33 @@ FB_UDR_BEGIN_FUNCTION(sum_args)
for (unsigned i = 0; i < inCount; ++i)
{
// Get null offset of the i-th input parameter.
inNullOffsets[i] = inMetadata->getNullOffset(status, i);
StatusException::check(status->get());
inNullOffsets[i] = StatusException::check(status, inMetadata->getNullOffset(status, i));
// Get the offset of the i-th input parameter.
inOffsets[i] = inMetadata->getOffset(status, i);
StatusException::check(status->get());
inOffsets[i] = StatusException::check(status, inMetadata->getOffset(status, i));
}
// Get output metadata.
AutoRelease<IMessageMetadata> outMetadata(metadata->getOutputMetadata(status));
StatusException::check(status->get());
AutoRelease<IMessageMetadata> outMetadata(StatusException::check(status,
metadata->getOutputMetadata(status)));
// Get null offset of the return value.
outNullOffset = outMetadata->getNullOffset(status, 0);
StatusException::check(status->get());
outNullOffset = StatusException::check(status, outMetadata->getNullOffset(status, 0));
// Get offset of the return value.
outOffset = outMetadata->getOffset(status, 0);
StatusException::check(status->get());
outOffset = StatusException::check(status, outMetadata->getOffset(status, 0));
}
// This function requires the INTEGER parameters and return value, otherwise it will crash.
// Metadata is inspected dynamically (in execute). This is not the fastest method.
FB_UDR_EXECUTE_DYNAMIC_FUNCTION
FB_UDR_EXECUTE_FUNCTION
{
*(ISC_SHORT*) (out + outNullOffset) = FB_FALSE;
// Get a reference to the return value.
ISC_LONG& ret = *(ISC_LONG*) (out + outOffset);
// By default, the return value is 0.
// The return value is automatically initialized to 0.
///ret = 0;
for (unsigned i = 0; i < inCount; ++i)
@ -321,38 +324,34 @@ create procedure gen_rows (
engine udr;
***/
FB_UDR_BEGIN_PROCEDURE(gen_rows)
// Without InMessage/OutMessage definitions, messages will be byte-based.
// Procedure variables.
unsigned inOffsetStart, inOffsetEnd, outNullOffset, outOffset;
// Get offsets once per procedure.
FB_UDR_CONSTRUCTOR
{
AutoRelease<IMessageMetadata> inMetadata(StatusException::check(status,
metadata->getInputMetadata(status)));
inOffsetStart = StatusException::check(status, inMetadata->getOffset(status, 0));
inOffsetEnd = StatusException::check(status, inMetadata->getOffset(status, 1));
AutoRelease<IMessageMetadata> outMetadata(StatusException::check(status,
metadata->getOutputMetadata(status)));
outNullOffset = StatusException::check(status, outMetadata->getNullOffset(status, 0));
outOffset = StatusException::check(status, outMetadata->getOffset(status, 0));
}
/*** Procedure destructor.
~FB_UDR_PROCEDURE(gen_rows)()
FB_UDR_DESTRUCTOR
{
}
***/
// Get offsets once per procedure.
FB_UDR_INITIALIZE
{
AutoRelease<IMessageMetadata> inMetadata(metadata->getInputMetadata(status));
StatusException::check(status->get());
inOffsetStart = inMetadata->getOffset(status, 0);
StatusException::check(status->get());
inOffsetEnd = inMetadata->getOffset(status, 1);
StatusException::check(status->get());
AutoRelease<IMessageMetadata> outMetadata(metadata->getOutputMetadata(status));
StatusException::check(status->get());
outNullOffset = outMetadata->getNullOffset(status, 0);
StatusException::check(status->get());
outOffset = outMetadata->getOffset(status, 0);
StatusException::check(status->get());
}
FB_UDR_EXECUTE_DYNAMIC_PROCEDURE
FB_UDR_EXECUTE_PROCEDURE
{
counter = *(ISC_LONG*) (in + procedure->inOffsetStart);
end = *(ISC_LONG*) (in + procedure->inOffsetEnd);
@ -360,13 +359,14 @@ FB_UDR_BEGIN_PROCEDURE(gen_rows)
*(ISC_SHORT*) (out + procedure->outNullOffset) = FB_FALSE;
}
// After procedure's execute definition, starts the result set definition.
FB_UDR_FETCH_PROCEDURE
{
if (counter > end)
return false;
*(ISC_LONG*) (out + procedure->outOffset) = counter++;
return true;
}
@ -393,11 +393,16 @@ create procedure gen_rows2 (
engine udr;
***/
FB_UDR_BEGIN_PROCEDURE(gen_rows2)
FB_UDR_EXECUTE_MESSAGE_PROCEDURE(
FB_MESSAGE(InMessage,
(FB_INTEGER, start)
(FB_INTEGER, end)
,
(FB_INTEGER, result))
);
FB_MESSAGE(OutMessage,
(FB_INTEGER, result)
);
FB_UDR_EXECUTE_PROCEDURE
{
out->resultNull = FB_FALSE;
out->result = in->start - 1;
@ -428,33 +433,36 @@ create procedure inc (
// metadata object.
// n3 and n4 are on the ResultSet scope, i.e., each procedure execution have they own instances.
FB_UDR_BEGIN_PROCEDURE(inc)
FB_MESSAGE(InMessage,
(FB_INTEGER, count)
);
FB_MESSAGE(OutMessage,
(FB_INTEGER, n0)
(FB_INTEGER, n1)
(FB_INTEGER, n2)
(FB_INTEGER, n3)
(FB_INTEGER, n4)
);
ISC_LONG n1;
// This is how a procedure (class) initializer is written.
// ResultSet variables are not accessible here.
// If there is nothing to initialize, it can be completelly suppressed.
FB_UDR_PROCEDURE(inc)()
: n1(0),
FB_UDR_CONSTRUCTOR
, n1(0),
n2(0)
{
}
ISC_LONG n2;
// FB_UDR_EXECUTE_MESSAGE_PROCEDURE or FB_UDR_EXECUTE_DYNAMIC_PROCEDURE starts the ResultSet scope.
FB_UDR_EXECUTE_MESSAGE_PROCEDURE(
(FB_INTEGER, count)
,
(FB_INTEGER, n0)
(FB_INTEGER, n1)
(FB_INTEGER, n2)
(FB_INTEGER, n3)
(FB_INTEGER, n4))
// This is the ResultSet (class) initializer. If there is nothing to initialize, the comma
// should be suppressed.
,
n3(procedure->n1), // n3 will start with the next value for n1 of the last execution
n4(0)
// FB_UDR_EXECUTE_PROCEDURE starts the ResultSet scope.
FB_UDR_EXECUTE_PROCEDURE
// This is the ResultSet (class) initializer.
, n3(procedure->n1), // n3 will start with the next value for n1 of the last execution
n4(0)
{
out->n0Null = out->n1Null = out->n2Null = out->n3Null = out->n4Null = FB_FALSE;
@ -472,8 +480,7 @@ FB_UDR_BEGIN_PROCEDURE(inc)
ISC_LONG n3;
// FB_UDR_FETCH must be always after FB_UDR_EXECUTE_MESSAGE_PROCEDURE or
// FB_UDR_EXECUTE_DYNAMIC_PROCEDURE.
// FB_UDR_FETCH_PROCEDURE must be always after FB_UDR_EXECUTE_PROCEDURE.
FB_UDR_FETCH_PROCEDURE
{
if (out->n0++ <= in->count)
@ -531,48 +538,27 @@ create trigger persons_replicate2
engine udr;
***/
FB_UDR_BEGIN_TRIGGER(replicate)
/***
FB_UDR_TRIGGER(replicate)()
: initialized(false)
{
}
// Without FieldsMessage definition, messages will be byte-based.
~FB_UDR_TRIGGER(replicate)()
{
if (!initialized)
return;
}
***/
FB_UDR_EXECUTE_DYNAMIC_TRIGGER
{
ITransaction* transaction = context->getTransaction(status);
StatusException::check(status->get());
// This will not work if the table has computed fields.
stmt->execute(status, transaction, triggerMetadata, newFields, NULL, NULL);
StatusException::check(status->get());
}
FB_UDR_INITIALIZE
FB_UDR_CONSTRUCTOR
, triggerMetadata(StatusException::check(status, metadata->getTriggerMetadata(status)))
{
ISC_STATUS_ARRAY statusVector = {0};
isc_db_handle dbHandle = getIscDbHandle(context);
isc_tr_handle trHandle = getIscTrHandle(context);
isc_stmt_handle stmtHandle = 0;
StatusException::check(isc_dsql_allocate_statement(statusVector, &dbHandle, &stmtHandle),
statusVector);
StatusException::check(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0,
StatusException::checkStatus(isc_dsql_allocate_statement(
statusVector, &dbHandle, &stmtHandle), statusVector);
StatusException::checkStatus(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0,
"select data_source from replicate_config where name = ?",
SQL_DIALECT_CURRENT, NULL), statusVector);
const char* table = metadata->getTriggerTable(status);
StatusException::check(status->get());
const char* table = StatusException::check(status, metadata->getTriggerTable(status));
// Skip the first exclamation point, separating the module name and entry point.
const char* info = strchr(metadata->getEntryPoint(status), '!');
StatusException::check(status->get());
const char* info = StatusException::check(status,
strchr(metadata->getEntryPoint(status), '!'));
// Skip the second exclamation point, separating the entry point and the misc info (config).
if (info)
@ -586,7 +572,7 @@ FB_UDR_BEGIN_TRIGGER(replicate)
XSQLDA* inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
inSqlDa->version = SQLDA_VERSION1;
inSqlDa->sqln = 1;
StatusException::check(isc_dsql_describe_bind(statusVector, &stmtHandle,
StatusException::checkStatus(isc_dsql_describe_bind(statusVector, &stmtHandle,
SQL_DIALECT_CURRENT, inSqlDa), statusVector);
inSqlDa->sqlvar[0].sqldata = new char[sizeof(short) + inSqlDa->sqlvar[0].sqllen];
strncpy(inSqlDa->sqlvar[0].sqldata + sizeof(short), info, inSqlDa->sqlvar[0].sqllen);
@ -595,24 +581,20 @@ FB_UDR_BEGIN_TRIGGER(replicate)
XSQLDA* outSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
outSqlDa->version = SQLDA_VERSION1;
outSqlDa->sqln = 1;
StatusException::check(isc_dsql_describe(statusVector, &stmtHandle,
StatusException::checkStatus(isc_dsql_describe(statusVector, &stmtHandle,
SQL_DIALECT_CURRENT, outSqlDa), statusVector);
outSqlDa->sqlvar[0].sqldata = new char[sizeof(short) + outSqlDa->sqlvar[0].sqllen + 1];
outSqlDa->sqlvar[0].sqldata[sizeof(short) + outSqlDa->sqlvar[0].sqllen] = '\0';
StatusException::check(isc_dsql_execute2(statusVector, &trHandle, &stmtHandle,
StatusException::checkStatus(isc_dsql_execute2(statusVector, &trHandle, &stmtHandle,
SQL_DIALECT_CURRENT, inSqlDa, outSqlDa), statusVector);
StatusException::check(isc_dsql_free_statement(statusVector, &stmtHandle, DSQL_unprepare),
statusVector);
StatusException::checkStatus(isc_dsql_free_statement(
statusVector, &stmtHandle, DSQL_unprepare), statusVector);
delete [] inSqlDa->sqlvar[0].sqldata;
delete [] reinterpret_cast<char*>(inSqlDa);
triggerMetadata.reset(metadata->getTriggerMetadata(status));
StatusException::check(status->get());
unsigned count = triggerMetadata->getCount(status);
StatusException::check(status->get());
unsigned count = StatusException::check(status, triggerMetadata->getCount(status));
char buffer[65536];
strcpy(buffer, "execute block (\n");
@ -622,8 +604,7 @@ FB_UDR_BEGIN_TRIGGER(replicate)
if (i > 0)
strcat(buffer, ",\n");
const char* name = triggerMetadata->getField(status, i);
StatusException::check(status->get());
const char* name = StatusException::check(status, triggerMetadata->getField(status, i));
strcat(buffer, " p");
sprintf(buffer + strlen(buffer), "%d type of column \"%s\".\"%s\" = ?", i, table, name);
@ -643,8 +624,7 @@ FB_UDR_BEGIN_TRIGGER(replicate)
if (i > 0)
strcat(buffer, ", ");
const char* name = triggerMetadata->getField(status, i);
StatusException::check(status->get());
const char* name = StatusException::check(status, triggerMetadata->getField(status, i));
strcat(buffer, "\"");
strcat(buffer, name);
@ -674,75 +654,65 @@ FB_UDR_BEGIN_TRIGGER(replicate)
strcat(buffer, outSqlDa->sqlvar[0].sqldata + sizeof(short));
strcat(buffer, "';\nend");
IAttachment* attachment = context->getAttachment(status);
StatusException::check(status->get());
IAttachment* attachment = StatusException::check(status, context->getAttachment(status));
ITransaction* transaction = StatusException::check(status, context->getTransaction(status));
ITransaction* transaction = context->getTransaction(status);
StatusException::check(status->get());
stmt.reset(attachment->prepare(status, transaction, 0, buffer, SQL_DIALECT_CURRENT, 0));
stmt.reset(StatusException::check(status,
attachment->prepare(status, transaction, 0, buffer, SQL_DIALECT_CURRENT, 0)));
delete [] outSqlDa->sqlvar[0].sqldata;
delete [] reinterpret_cast<char*>(outSqlDa);
///initialized = true;
}
///bool initialized;
/***
FB_UDR_DESTRUCTOR
{
}
***/
FB_UDR_EXECUTE_TRIGGER
{
ITransaction* transaction = StatusException::check(status, context->getTransaction(status));
// This will not work if the table has computed fields.
stmt->execute(status, transaction, triggerMetadata, newFields, NULL, NULL);
StatusException::check(status->get());
}
AutoRelease<IMessageMetadata> triggerMetadata;
AutoRelease<IStatement> stmt;
FB_UDR_END_TRIGGER
FB_UDR_BEGIN_TRIGGER(replicate_persons)
/***
FB_UDR_TRIGGER(replicate_persons)()
: initialized(false)
{
}
~FB_UDR_TRIGGER(replicate_persons)()
{
if (!initialized)
return;
}
***/
// Order of fields does not need to match the fields order in the table, but it should match
// the order of fields in the SQL command constructed in the initialization.
FB_UDR_EXECUTE_MESSAGE_TRIGGER(
FB_TRIGGER_MESSAGE(FieldsMessage,
(FB_INTEGER, id, "ID")
(FB_BLOB, info, "INFO")
(FB_VARCHAR(60 * 4), address, "ADDRESS")
(FB_VARCHAR(60 * 4), name, "NAME")
)
{
ITransaction* transaction = context->getTransaction(status);
StatusException::check(status->get());
);
stmt->execute(status, transaction, triggerMetadata, newFields, NULL, NULL);
StatusException::check(status->get());
}
FB_UDR_INITIALIZE
FB_UDR_CONSTRUCTOR
, triggerMetadata(StatusException::check(status, metadata->getTriggerMetadata(status)))
{
ISC_STATUS_ARRAY statusVector = {0};
isc_db_handle dbHandle = getIscDbHandle(context);
isc_tr_handle trHandle = getIscTrHandle(context);
isc_stmt_handle stmtHandle = 0;
StatusException::check(isc_dsql_allocate_statement(statusVector, &dbHandle, &stmtHandle),
statusVector);
StatusException::check(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0,
StatusException::checkStatus(isc_dsql_allocate_statement(
statusVector, &dbHandle, &stmtHandle), statusVector);
StatusException::checkStatus(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0,
"select data_source from replicate_config where name = ?",
SQL_DIALECT_CURRENT, NULL), statusVector);
const char* table = metadata->getTriggerTable(status);
StatusException::check(status->get());
const char* table = StatusException::check(status, metadata->getTriggerTable(status));
// Skip the first exclamation point, separating the module name and entry point.
const char* info = strchr(metadata->getEntryPoint(status), '!');
StatusException::check(status->get());
const char* info = StatusException::check(status,
strchr(metadata->getEntryPoint(status), '!'));
// Skip the second exclamation point, separating the entry point and the misc info (config).
if (info)
@ -756,8 +726,8 @@ FB_UDR_BEGIN_TRIGGER(replicate_persons)
XSQLDA* inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
inSqlDa->version = SQLDA_VERSION1;
inSqlDa->sqln = 1;
StatusException::check(isc_dsql_describe_bind(statusVector, &stmtHandle,
SQL_DIALECT_CURRENT, inSqlDa), statusVector);
StatusException::checkStatus(isc_dsql_describe_bind(
statusVector, &stmtHandle, SQL_DIALECT_CURRENT, inSqlDa), statusVector);
inSqlDa->sqlvar[0].sqldata = new char[sizeof(short) + inSqlDa->sqlvar[0].sqllen];
strncpy(inSqlDa->sqlvar[0].sqldata + sizeof(short), info, inSqlDa->sqlvar[0].sqllen);
*reinterpret_cast<short*>(inSqlDa->sqlvar[0].sqldata) = strlen(info);
@ -765,22 +735,19 @@ FB_UDR_BEGIN_TRIGGER(replicate_persons)
XSQLDA* outSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
outSqlDa->version = SQLDA_VERSION1;
outSqlDa->sqln = 1;
StatusException::check(isc_dsql_describe(statusVector, &stmtHandle,
SQL_DIALECT_CURRENT, outSqlDa), statusVector);
StatusException::checkStatus(isc_dsql_describe(
statusVector, &stmtHandle, SQL_DIALECT_CURRENT, outSqlDa), statusVector);
outSqlDa->sqlvar[0].sqldata = new char[sizeof(short) + outSqlDa->sqlvar[0].sqllen + 1];
outSqlDa->sqlvar[0].sqldata[sizeof(short) + outSqlDa->sqlvar[0].sqllen] = '\0';
StatusException::check(isc_dsql_execute2(statusVector, &trHandle, &stmtHandle,
StatusException::checkStatus(isc_dsql_execute2(statusVector, &trHandle, &stmtHandle,
SQL_DIALECT_CURRENT, inSqlDa, outSqlDa), statusVector);
StatusException::check(isc_dsql_free_statement(statusVector, &stmtHandle, DSQL_unprepare),
statusVector);
StatusException::checkStatus(isc_dsql_free_statement(
statusVector, &stmtHandle, DSQL_unprepare), statusVector);
delete [] inSqlDa->sqlvar[0].sqldata;
delete [] reinterpret_cast<char*>(inSqlDa);
triggerMetadata.reset(metadata->getTriggerMetadata(status));
StatusException::check(status->get());
char buffer[65536];
strcpy(buffer,
"execute block (\n"
@ -797,21 +764,30 @@ FB_UDR_BEGIN_TRIGGER(replicate_persons)
strcat(buffer, outSqlDa->sqlvar[0].sqldata + sizeof(short));
strcat(buffer, "';\nend");
IAttachment* attachment = context->getAttachment(status);
StatusException::check(status->get());
IAttachment* attachment = StatusException::check(status, context->getAttachment(status));
ITransaction* transaction = StatusException::check(status, context->getTransaction(status));
ITransaction* transaction = context->getTransaction(status);
StatusException::check(status->get());
stmt.reset(attachment->prepare(status, transaction, 0, buffer, SQL_DIALECT_CURRENT, 0));
stmt.reset(StatusException::check(status,
attachment->prepare(status, transaction, 0, buffer, SQL_DIALECT_CURRENT, 0)));
delete [] outSqlDa->sqlvar[0].sqldata;
delete [] reinterpret_cast<char*>(outSqlDa);
///initialized = true;
}
///bool initialized;
/***
FB_UDR_DESTRUCTOR
{
}
***/
FB_UDR_EXECUTE_TRIGGER
{
ITransaction* transaction = StatusException::check(status, context->getTransaction(status));
stmt->execute(status, transaction, triggerMetadata, newFields, NULL, NULL);
StatusException::check(status->get());
}
AutoRelease<IMessageMetadata> triggerMetadata;
AutoRelease<IStatement> stmt;
FB_UDR_END_TRIGGER

View File

@ -81,7 +81,7 @@ public:
class ExternalResultSet : public IDisposable
{
public:
virtual bool FB_CARG fetch(IStatus* status) = 0;
virtual FB_BOOLEAN FB_CARG fetch(IStatus* status) = 0;
};
#define FB_EXTERNAL_RESULT_SET_VERSION (FB_DISPOSABLE_VERSION + 1)

View File

@ -40,51 +40,23 @@ namespace Firebird
//------------------------------------------------------------------------------
#define FB_UDR_FUNCTION(name) Func##name
#define FB_UDR_PROCEDURE(name) Proc##name
#define FB_UDR_TRIGGER(name) Trig##name
#define FB_UDR_BEGIN_FUNCTION(name) \
class FB_UDR_FUNCTION(name); \
\
::Firebird::Udr::FunctionFactoryImpl<FB_UDR_FUNCTION(name)> FuncFactory##name(#name); \
\
class FB_UDR_FUNCTION(name) : public ::Firebird::Udr::Function<FB_UDR_FUNCTION(name)> \
namespace Func##name \
{ \
public: \
void initialize(::Firebird::IStatus* /*status*/, void*) \
class Impl; \
\
static ::Firebird::Udr::FunctionFactoryImpl<Impl> factory(#name); \
\
class Impl : public ::Firebird::Udr::Function<Impl> \
{ \
}
public: \
FB__UDR_COMMON_IMPL
#define FB_UDR_END_FUNCTION \
};
}; \
}
#define FB_UDR_EXECUTE_DYNAMIC_FUNCTION \
FB__UDR_DYNAMIC_TYPE(InMessage); \
FB__UDR_DYNAMIC_TYPE(OutMessage); \
\
FB__UDR_EXECUTE_FUNCTION
#define FB_UDR_EXECUTE_MESSAGE_FUNCTION(inputs, output) \
FB_MESSAGE(InMessage, \
inputs \
); \
FB_MESSAGE(OutMessage, \
output \
); \
\
FB__UDR_EXECUTE_FUNCTION
#define FB_UDR_EXECUTE_MESSAGE_FUNCTION_OUT(outputs) \
FB__UDR_DYNAMIC_TYPE(InMessage); \
FB_MESSAGE(OutMessage, \
outputs \
); \
\
FB__UDR_EXECUTE_FUNCTION
#define FB__UDR_EXECUTE_FUNCTION \
#define FB_UDR_EXECUTE_FUNCTION \
virtual void FB_CARG execute(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
void* in, void* out) \
{ \
@ -100,56 +72,23 @@ namespace Firebird
#define FB_UDR_BEGIN_PROCEDURE(name) \
class FB_UDR_PROCEDURE(name); \
\
::Firebird::Udr::ProcedureFactoryImpl<FB_UDR_PROCEDURE(name)> ProcFactory##name(#name); \
\
class FB_UDR_PROCEDURE(name) : public ::Firebird::Udr::Procedure<FB_UDR_PROCEDURE(name)> \
namespace Proc##name \
{ \
public: \
typedef FB_UDR_PROCEDURE(name) This; \
class Impl; \
\
void initialize(::Firebird::IStatus* /*status*/, void*) \
static ::Firebird::Udr::ProcedureFactoryImpl<Impl> factory(#name); \
\
class Impl : public ::Firebird::Udr::Procedure<Impl> \
{ \
}
public: \
FB__UDR_COMMON_IMPL
#define FB_UDR_END_PROCEDURE \
}; \
}; \
};
}
#define FB_UDR_EXECUTE_DYNAMIC_PROCEDURE \
FB__UDR_DYNAMIC_TYPE(InMessage); \
FB__UDR_DYNAMIC_TYPE(OutMessage); \
\
FB__UDR_EXECUTE_PROCEDURE
#define FB_UDR_EXECUTE_MESSAGE_PROCEDURE(inputs, outputs) \
FB_MESSAGE(InMessage, \
inputs \
); \
FB_MESSAGE(OutMessage, \
outputs \
); \
\
FB__UDR_EXECUTE_PROCEDURE
#define FB_UDR_EXECUTE_MESSAGE_PROCEDURE_IN(inputs) \
FB_MESSAGE(InMessage, \
inputs \
); \
FB__UDR_DYNAMIC_TYPE(OutMessage); \
\
FB__UDR_EXECUTE_PROCEDURE
#define FB_UDR_EXECUTE_MESSAGE_PROCEDURE_OUT(outputs) \
FB__UDR_DYNAMIC_TYPE(InMessage); \
FB_MESSAGE(OutMessage, \
outputs \
); \
\
FB__UDR_EXECUTE_PROCEDURE
#define FB__UDR_EXECUTE_PROCEDURE \
#define FB_UDR_EXECUTE_PROCEDURE \
virtual ::Firebird::ExternalResultSet* FB_CARG open(::Firebird::IStatus* status, \
::Firebird::ExternalContext* context, void* in, void* out) \
{ \
@ -159,61 +98,49 @@ namespace Firebird
} \
FB__UDR_CATCH \
\
return 0; \
return NULL; \
} \
\
class ResultSet : public ::Firebird::Udr::ResultSet<ResultSet, This, InMessage, OutMessage> \
class ResultSet : public ::Firebird::Udr::ResultSet<ResultSet, Impl, InMessage, OutMessage> \
{ \
public: \
ResultSet(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
This* const procedure, InMessage::Type* const in, OutMessage::Type* const out) \
: ::Firebird::Udr::ResultSet<ResultSet, This, InMessage, OutMessage>( \
Impl* const procedure, InMessage::Type* const in, OutMessage::Type* const out) \
: ::Firebird::Udr::ResultSet<ResultSet, Impl, InMessage, OutMessage>( \
context, procedure, in, out)
#define FB_UDR_FETCH_PROCEDURE \
virtual bool FB_CARG fetch(::Firebird::IStatus* status) \
virtual FB_BOOLEAN FB_CARG fetch(::Firebird::IStatus* status) \
{ \
try \
{ \
return internalFetch(status); \
return (FB_BOOLEAN) internalFetch(status); \
} \
FB__UDR_CATCH \
\
return 0; \
return FB_FALSE; \
} \
\
bool internalFetch(::Firebird::IStatus* status)
#define FB_UDR_BEGIN_TRIGGER(name) \
class FB_UDR_TRIGGER(name); \
\
::Firebird::Udr::TriggerFactoryImpl<FB_UDR_TRIGGER(name)> TrigFactory##name(#name); \
\
class FB_UDR_TRIGGER(name) : public ::Firebird::Udr::Trigger<FB_UDR_TRIGGER(name)> \
namespace Trig##name \
{ \
public: \
class Impl; \
\
void initialize(::Firebird::IStatus* /*status*/, void*) \
static ::Firebird::Udr::TriggerFactoryImpl<Impl> factory(#name); \
\
class Impl : public ::Firebird::Udr::Trigger<Impl> \
{ \
}
public: \
FB__UDR_COMMON_IMPL
#define FB_UDR_END_TRIGGER \
};
}; \
}
#define FB_UDR_EXECUTE_DYNAMIC_TRIGGER \
FB__UDR_DYNAMIC_TYPE(FieldsMessage); \
\
FB__UDR_EXECUTE_TRIGGER
#define FB_UDR_EXECUTE_MESSAGE_TRIGGER(fields) \
FB_TRIGGER_MESSAGE(FieldsMessage, \
fields \
); \
\
FB__UDR_EXECUTE_TRIGGER
#define FB__UDR_EXECUTE_TRIGGER \
#define FB_UDR_EXECUTE_TRIGGER \
virtual void FB_CARG execute(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
::Firebird::ExternalTrigger::Action action, void* oldFields, void* newFields) \
{ \
@ -230,27 +157,34 @@ namespace Firebird
FieldsMessage::Type* oldFields, FieldsMessage::Type* newFields)
#define FB_UDR_INITIALIZE \
void initialize(::Firebird::IStatus* status, ExternalContext* context) \
#define FB_UDR_CONSTRUCTOR \
Impl(::Firebird::IStatus* const status, ExternalContext* const context, \
const IRoutineMetadata* const metadata__) \
: master(context->getMaster()), \
metadata(metadata__)
#define FB_UDR_DESTRUCTOR \
~Impl()
#define FB__UDR_COMMON_IMPL \
Impl(const void* const, ExternalContext* const context, \
const IRoutineMetadata* const aMetadata) \
: master(context->getMaster()), \
metadata(aMetadata) \
{ \
try \
{ \
internalInitialize(status, context); \
} \
FB__UDR_CATCH \
} \
\
void internalInitialize(::Firebird::IStatus* status, ::Firebird::ExternalContext* context)
IMaster* master; \
const IRoutineMetadata* metadata;
#define FB__UDR_DYNAMIC_TYPE(name) \
#define FB__UDR_COMMON_TYPE(name) \
struct name \
{ \
typedef unsigned char Type; \
static void setup(::Firebird::IStatus*, ::Firebird::IMetadataBuilder*) {} \
}
#define FB__UDR_CATCH \
catch (const ::Firebird::Udr::StatusException& e) \
{ \
@ -313,7 +247,7 @@ public:
throw StatusException(vector);
}
static void check(ISC_STATUS status, const ISC_STATUS* vector)
static void checkStatus(ISC_STATUS status, const ISC_STATUS* vector)
{
if (status == 0)
return;
@ -321,6 +255,13 @@ public:
check(vector);
}
template <typename T>
static T check(IStatus* status, T value)
{
check(status->get());
return value;
}
public:
const ISC_STATUS* getStatusVector() const
{
@ -479,22 +420,13 @@ protected:
};
// This class is used to fix an apparent bug with clang, where the object is wrongly initialized
// and overwrites the members set in the operator new.
template <typename T>
class Routine : public T
{
public:
Routine()
{
}
};
template <typename This>
class Function : public ExternalFunction, public Helper
{
public:
FB__UDR_COMMON_TYPE(InMessage);
FB__UDR_COMMON_TYPE(OutMessage);
virtual int FB_CARG getVersion()
{
return FB_EXTERNAL_FUNCTION_VERSION;
@ -514,23 +446,6 @@ public:
Utf8* /*name*/, uint /*nameSize*/)
{
}
void* operator new(size_t size, IMaster* master, const IRoutineMetadata* metadata)
{
Function* p = reinterpret_cast<Function*>(::new char[size]);
p->master = master;
p->metadata = metadata;
return p;
}
void operator delete(void* p)
{
::delete [] static_cast<char*>(p);
}
public:
IMaster* master;
const IRoutineMetadata* metadata;
};
@ -538,6 +453,9 @@ template <typename This>
class Procedure : public ExternalProcedure, public Helper
{
public:
FB__UDR_COMMON_TYPE(InMessage);
FB__UDR_COMMON_TYPE(OutMessage);
virtual int FB_CARG getVersion()
{
return FB_EXTERNAL_PROCEDURE_VERSION;
@ -557,23 +475,6 @@ public:
Utf8* /*name*/, uint /*nameSize*/)
{
}
void* operator new(size_t size, IMaster* master, const IRoutineMetadata* metadata)
{
Procedure* p = reinterpret_cast<Procedure*>(::new char[size]);
p->master = master;
p->metadata = metadata;
return p;
}
void operator delete(void* p)
{
::delete [] static_cast<char*>(p);
}
public:
IMaster* master;
const IRoutineMetadata* metadata;
};
@ -581,6 +482,8 @@ template <typename This>
class Trigger : public ExternalTrigger, public Helper
{
public:
FB__UDR_COMMON_TYPE(FieldsMessage);
virtual int FB_CARG getVersion()
{
return FB_EXTERNAL_TRIGGER_VERSION;
@ -600,23 +503,6 @@ public:
Utf8* /*name*/, uint /*nameSize*/)
{
}
void* operator new(size_t size, IMaster* master, const IRoutineMetadata* metadata)
{
Trigger* p = reinterpret_cast<Trigger*>(::new char[size]);
p->master = master;
p->metadata = metadata;
return p;
}
void operator delete(void* p)
{
::delete [] static_cast<char*>(p);
}
public:
IMaster* master;
const IRoutineMetadata* metadata;
};
@ -638,9 +524,13 @@ public:
virtual ExternalFunction* FB_CARG newItem(IStatus* status, ExternalContext* context,
const IRoutineMetadata* metadata)
{
T* obj = new(context->getMaster(), metadata) Routine<T>;
obj->initialize(status, context);
return obj;
try
{
return new T(status, context, metadata);
}
FB__UDR_CATCH
return NULL;
}
};
@ -663,9 +553,13 @@ public:
virtual ExternalProcedure* FB_CARG newItem(IStatus* status, ExternalContext* context,
const IRoutineMetadata* metadata)
{
T* obj = new(context->getMaster(), metadata) Routine<T>;
obj->initialize(status, context);
return obj;
try
{
return new T(status, context, metadata);
}
FB__UDR_CATCH
return NULL;
}
};
@ -687,9 +581,13 @@ public:
virtual ExternalTrigger* FB_CARG newItem(IStatus* status, ExternalContext* context,
const IRoutineMetadata* metadata)
{
T* obj = new(context->getMaster(), metadata) Routine<T>;
obj->initialize(status, context);
return obj;
try
{
return new T(status, context, metadata);
}
FB__UDR_CATCH
return NULL;
}
};