mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Work in progress fixing external triggers.
This commit is contained in:
parent
1652cf93d7
commit
b9bc308a72
@ -410,7 +410,6 @@ FB_UDR_BEGIN_PROCEDURE(inc)
|
||||
FB_UDR_END_PROCEDURE
|
||||
|
||||
|
||||
#if 0 //// FIXME:
|
||||
/***
|
||||
Sample usage:
|
||||
|
||||
@ -460,52 +459,20 @@ FB_UDR_BEGIN_TRIGGER(replicate)
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < inSqlDa->sqln; ++i)
|
||||
{
|
||||
XSQLVAR* var = &inSqlDa->sqlvar[i];
|
||||
delete [] var->sqldata;
|
||||
delete var->sqlind;
|
||||
}
|
||||
StatusImpl status(master);
|
||||
|
||||
delete [] reinterpret_cast<char*>(inSqlDa);
|
||||
|
||||
ISC_STATUS_ARRAY statusVector = {0};
|
||||
isc_dsql_free_statement(statusVector, &stmtHandle, DSQL_drop);
|
||||
triggerMetadata->release();
|
||||
stmt->free(&status);
|
||||
}
|
||||
|
||||
FB_UDR_EXECUTE_DYNAMIC_TRIGGER
|
||||
{
|
||||
///AutoDispose<IStatus> status(master->getStatus());
|
||||
|
||||
const IParametersMetadata* fields = metadata->getTriggerFields(status);
|
||||
ITransaction* transaction = context->getTransaction(status);
|
||||
StatusException::check(status->get());
|
||||
|
||||
unsigned fieldsCount = fields->getCount(status);
|
||||
// This will not work if the table has computed fields.
|
||||
stmt->execute(status, transaction, triggerMetadata, newFields, NULL, NULL);
|
||||
StatusException::check(status->get());
|
||||
|
||||
MessageImpl message(fieldsCount, newFields);
|
||||
|
||||
ISC_STATUS_ARRAY statusVector = {0};
|
||||
isc_db_handle dbHandle = getIscDbHandle(context);
|
||||
isc_tr_handle trHandle = getIscTrHandle(context);
|
||||
|
||||
for (unsigned i = 1; i <= fieldsCount; ++i)
|
||||
{
|
||||
ParamDesc<void*> field(message, fields);
|
||||
|
||||
XSQLVAR* var = &inSqlDa->sqlvar[i - 1];
|
||||
|
||||
if (message.isNull(field))
|
||||
*var->sqlind = -1;
|
||||
else
|
||||
{
|
||||
*var->sqlind = 0;
|
||||
memcpy(var->sqldata, message[field], var->sqllen);
|
||||
}
|
||||
}
|
||||
|
||||
StatusException::check(isc_dsql_execute(statusVector, &trHandle, &stmtHandle, SQL_DIALECT_CURRENT,
|
||||
inSqlDa), statusVector);
|
||||
}
|
||||
|
||||
FB_UDR_INITIALIZE
|
||||
@ -514,8 +481,9 @@ FB_UDR_BEGIN_TRIGGER(replicate)
|
||||
isc_db_handle dbHandle = getIscDbHandle(context);
|
||||
isc_tr_handle trHandle = getIscTrHandle(context);
|
||||
|
||||
stmtHandle = 0;
|
||||
StatusException::check(isc_dsql_allocate_statement(statusVector, &dbHandle, &stmtHandle), statusVector);
|
||||
isc_stmt_handle stmtHandle = 0;
|
||||
StatusException::check(isc_dsql_allocate_statement(statusVector, &dbHandle, &stmtHandle),
|
||||
statusVector);
|
||||
StatusException::check(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0,
|
||||
"select data_source from replicate_config where name = ?",
|
||||
SQL_DIALECT_CURRENT, NULL), statusVector);
|
||||
@ -538,11 +506,11 @@ FB_UDR_BEGIN_TRIGGER(replicate)
|
||||
else
|
||||
info = "";
|
||||
|
||||
inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
|
||||
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::check(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);
|
||||
@ -550,23 +518,23 @@ 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, SQL_DIALECT_CURRENT, outSqlDa),
|
||||
statusVector);
|
||||
StatusException::check(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, SQL_DIALECT_CURRENT,
|
||||
inSqlDa, outSqlDa), statusVector);
|
||||
StatusException::check(isc_dsql_free_statement(statusVector, &stmtHandle, DSQL_unprepare), statusVector);
|
||||
StatusException::check(isc_dsql_execute2(statusVector, &trHandle, &stmtHandle,
|
||||
SQL_DIALECT_CURRENT, inSqlDa, outSqlDa), statusVector);
|
||||
StatusException::check(isc_dsql_free_statement(statusVector, &stmtHandle, DSQL_unprepare),
|
||||
statusVector);
|
||||
|
||||
delete [] inSqlDa->sqlvar[0].sqldata;
|
||||
delete [] reinterpret_cast<char*>(inSqlDa);
|
||||
inSqlDa = NULL;
|
||||
|
||||
const IParametersMetadata* fields = metadata->getTriggerFields(status);
|
||||
triggerMetadata = metadata->getTriggerMetadata(status);
|
||||
StatusException::check(status->get());
|
||||
|
||||
unsigned count = fields->getCount(status);
|
||||
unsigned count = triggerMetadata->getCount(status);
|
||||
StatusException::check(status->get());
|
||||
|
||||
char buffer[65536];
|
||||
@ -577,7 +545,7 @@ FB_UDR_BEGIN_TRIGGER(replicate)
|
||||
if (i > 0)
|
||||
strcat(buffer, ",\n");
|
||||
|
||||
const char* name = fields->getField(status, i);
|
||||
const char* name = triggerMetadata->getField(status, i);
|
||||
StatusException::check(status->get());
|
||||
|
||||
strcat(buffer, " p");
|
||||
@ -598,7 +566,7 @@ FB_UDR_BEGIN_TRIGGER(replicate)
|
||||
if (i > 0)
|
||||
strcat(buffer, ", ");
|
||||
|
||||
const char* name = fields->getField(status, i);
|
||||
const char* name = triggerMetadata->getField(status, i);
|
||||
StatusException::check(status->get());
|
||||
|
||||
strcat(buffer, "\"");
|
||||
@ -629,68 +597,13 @@ FB_UDR_BEGIN_TRIGGER(replicate)
|
||||
strcat(buffer, outSqlDa->sqlvar[0].sqldata + sizeof(short));
|
||||
strcat(buffer, "';\nend");
|
||||
|
||||
StatusException::check(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0, buffer,
|
||||
SQL_DIALECT_CURRENT, NULL), statusVector);
|
||||
IAttachment* attachment = context->getAttachment(status);
|
||||
StatusException::check(status->get());
|
||||
|
||||
inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(count))]);
|
||||
inSqlDa->version = SQLDA_VERSION1;
|
||||
inSqlDa->sqln = count;
|
||||
StatusException::check(isc_dsql_describe_bind(statusVector, &stmtHandle, SQL_DIALECT_CURRENT, inSqlDa),
|
||||
statusVector);
|
||||
ITransaction* transaction = context->getTransaction(status);
|
||||
StatusException::check(status->get());
|
||||
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
{
|
||||
XSQLVAR* var = &inSqlDa->sqlvar[i];
|
||||
|
||||
switch (var->sqltype & ~1)
|
||||
{
|
||||
case SQL_TEXT:
|
||||
var->sqldata = new char[var->sqllen];
|
||||
break;
|
||||
|
||||
case SQL_VARYING:
|
||||
var->sqldata = new char[var->sqllen];
|
||||
var->sqllen += sizeof(short);
|
||||
break;
|
||||
|
||||
case SQL_SHORT:
|
||||
var->sqldata = new char[sizeof(short)];
|
||||
break;
|
||||
|
||||
case SQL_LONG:
|
||||
var->sqldata = new char[sizeof(int32)];
|
||||
break;
|
||||
|
||||
case SQL_INT64:
|
||||
var->sqldata = new char[sizeof(int64)];
|
||||
break;
|
||||
|
||||
case SQL_FLOAT:
|
||||
var->sqltype = SQL_DOUBLE;
|
||||
var->sqllen = sizeof(double);
|
||||
// fall into
|
||||
|
||||
case SQL_DOUBLE:
|
||||
var->sqldata = new char[sizeof(double)];
|
||||
break;
|
||||
|
||||
case SQL_TYPE_DATE:
|
||||
var->sqldata = new char[sizeof(ISC_DATE)];
|
||||
break;
|
||||
|
||||
//// TODO: SQL_TIMESTAMP, SQL_TYPE_TIME
|
||||
|
||||
case SQL_BLOB:
|
||||
var->sqldata = new char[sizeof(ISC_QUAD)];
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
var->sqltype |= 1;
|
||||
var->sqlind = new short(-1);
|
||||
}
|
||||
stmt = attachment->prepare(status, transaction, 0, buffer, 3, 0);
|
||||
|
||||
delete [] outSqlDa->sqlvar[0].sqldata;
|
||||
delete [] reinterpret_cast<char*>(outSqlDa);
|
||||
@ -699,11 +612,12 @@ FB_UDR_BEGIN_TRIGGER(replicate)
|
||||
}
|
||||
|
||||
bool initialized;
|
||||
XSQLDA* inSqlDa;
|
||||
isc_stmt_handle stmtHandle;
|
||||
IMessageMetadata* triggerMetadata;
|
||||
IStatement* stmt;
|
||||
FB_UDR_END_TRIGGER
|
||||
|
||||
|
||||
#if 0 //// FIXME:
|
||||
FB_UDR_BEGIN_TRIGGER(replicate_persons)
|
||||
FB_UDR_TRIGGER(replicate_persons)()
|
||||
: initialized(false)
|
||||
|
@ -38,15 +38,6 @@ namespace Firebird {
|
||||
class ExternalEngine;
|
||||
|
||||
|
||||
class ITriggerMessage : public IVersioned
|
||||
{
|
||||
public:
|
||||
virtual void FB_CARG set(const unsigned char* blr, unsigned blrLength, unsigned bufferLength,
|
||||
const char** names, unsigned count) = 0;
|
||||
};
|
||||
#define FB_TRIGGER_MESSAGE_VERSION (FB_VERSIONED_VERSION + 1)
|
||||
|
||||
|
||||
// Connection to current database in external engine.
|
||||
// Context passed to ExternalEngine has SYSDBA privileges.
|
||||
// Context passed to ExternalFunction, ExternalProcedure and ExternalTrigger
|
||||
@ -169,7 +160,7 @@ public:
|
||||
virtual const char* FB_CARG getBody(IStatus* status) const = 0;
|
||||
virtual IMessageMetadata* FB_CARG getInputMetadata(IStatus* status) const = 0;
|
||||
virtual IMessageMetadata* FB_CARG getOutputMetadata(IStatus* status) const = 0;
|
||||
virtual const IMessageMetadata* FB_CARG getTriggerFields(IStatus* status) const = 0;
|
||||
virtual IMessageMetadata* FB_CARG getTriggerMetadata(IStatus* status) const = 0;
|
||||
virtual const char* FB_CARG getTriggerTable(IStatus* status) const = 0;
|
||||
virtual ExternalTrigger::Type FB_CARG getTriggerType(IStatus* status) const = 0;
|
||||
};
|
||||
@ -203,7 +194,7 @@ public:
|
||||
const IRoutineMetadata* metadata,
|
||||
IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) = 0;
|
||||
virtual ExternalTrigger* FB_CALL makeTrigger(IStatus* status, ExternalContext* context,
|
||||
const IRoutineMetadata* metadata, ITriggerMessage* triggerMsg) = 0;
|
||||
const IRoutineMetadata* metadata, IMetadataBuilder* fieldsBuilder) = 0;
|
||||
};
|
||||
#define FB_EXTERNAL_ENGINE_VERSION (FB_PLUGIN_VERSION + 6)
|
||||
|
||||
|
@ -202,7 +202,7 @@ namespace Firebird
|
||||
};
|
||||
|
||||
#define FB_UDR_EXECUTE_DYNAMIC_TRIGGER \
|
||||
typedef void* FieldsMessage; \
|
||||
FB_UDR__DYNAMIC_TYPE(FieldsMessage); \
|
||||
\
|
||||
FB_UDR__EXECUTE_TRIGGER
|
||||
|
||||
@ -219,13 +219,15 @@ namespace Firebird
|
||||
{ \
|
||||
try \
|
||||
{ \
|
||||
internalExecute(status, context, action, (FieldsMessage*) oldFields, (FieldsMessage*) newFields); \
|
||||
internalExecute(status, context, action, \
|
||||
(FieldsMessage::Type*) oldFields, (FieldsMessage::Type*) newFields); \
|
||||
} \
|
||||
FB_UDR__CATCH \
|
||||
} \
|
||||
\
|
||||
void internalExecute(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
|
||||
::Firebird::ExternalTrigger::Action action, FieldsMessage* oldFields, FieldsMessage* newFields)
|
||||
::Firebird::ExternalTrigger::Action action, \
|
||||
FieldsMessage::Type* oldFields, FieldsMessage::Type* newFields)
|
||||
|
||||
|
||||
#define FB_UDR_INITIALIZE \
|
||||
@ -631,7 +633,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void setup(IStatus* status, ExternalContext* /*context*/,
|
||||
const IRoutineMetadata* /*metadata*/, ITriggerMessage* fields)
|
||||
const IRoutineMetadata* /*metadata*/, IMetadataBuilder* fields)
|
||||
{
|
||||
T::FieldsMessage::setup(status, fields);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class TriggerFactory
|
||||
{
|
||||
public:
|
||||
virtual void setup(IStatus* status, ExternalContext* context, const IRoutineMetadata* metadata,
|
||||
ITriggerMessage* fields) = 0;
|
||||
IMetadataBuilder* fieldsBuilder) = 0;
|
||||
virtual ExternalTrigger* FB_CALL newItem(IStatus* status, ExternalContext* context,
|
||||
const IRoutineMetadata* metadata) = 0;
|
||||
};
|
||||
|
@ -61,6 +61,7 @@ namespace Jrd {
|
||||
static MakeUpgradeInfo<> upInfo;
|
||||
|
||||
|
||||
// Create a Format based on a IMessageMetadata.
|
||||
static Format* createFormat(MemoryPool& pool, IMessageMetadata* params)
|
||||
{
|
||||
LocalStatus status;
|
||||
@ -227,11 +228,22 @@ ExtEngineManager::ExternalContextImpl::ExternalContextImpl(thread_db* tdbb,
|
||||
//// TODO: admin rights
|
||||
|
||||
clientCharSet = INTL_charset_lookup(tdbb, internalAttachment->att_client_charset)->getName();
|
||||
|
||||
internalAttachment->att_interface->addRef();
|
||||
|
||||
externalAttachment = MasterInterfacePtr()->registerAttachment(JProvider::getInstance(),
|
||||
internalAttachment->att_interface);
|
||||
}
|
||||
|
||||
ExtEngineManager::ExternalContextImpl::~ExternalContextImpl()
|
||||
{
|
||||
releaseTransaction();
|
||||
|
||||
if (externalAttachment)
|
||||
{
|
||||
externalAttachment->release();
|
||||
externalAttachment = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ExtEngineManager::ExternalContextImpl::releaseTransaction()
|
||||
@ -242,12 +254,6 @@ void ExtEngineManager::ExternalContextImpl::releaseTransaction()
|
||||
externalTransaction = NULL;
|
||||
}
|
||||
|
||||
if (externalAttachment)
|
||||
{
|
||||
externalAttachment->release();
|
||||
externalAttachment = NULL;
|
||||
}
|
||||
|
||||
internalTransaction = NULL;
|
||||
}
|
||||
|
||||
@ -259,23 +265,13 @@ void ExtEngineManager::ExternalContextImpl::setTransaction(thread_db* tdbb)
|
||||
return;
|
||||
|
||||
releaseTransaction();
|
||||
fb_assert(!externalAttachment && !externalTransaction);
|
||||
|
||||
MasterInterfacePtr master;
|
||||
|
||||
if (internalAttachment)
|
||||
{
|
||||
internalAttachment->att_interface->addRef();
|
||||
|
||||
externalAttachment = master->registerAttachment(JProvider::getInstance(),
|
||||
internalAttachment->att_interface);
|
||||
}
|
||||
fb_assert(!externalTransaction);
|
||||
|
||||
if ((internalTransaction = newTransaction))
|
||||
{
|
||||
internalTransaction->getInterface()->addRef();
|
||||
|
||||
externalTransaction = master->registerTransaction(externalAttachment,
|
||||
externalTransaction = MasterInterfacePtr()->registerTransaction(externalAttachment,
|
||||
internalTransaction->getInterface());
|
||||
}
|
||||
}
|
||||
@ -470,7 +466,7 @@ bool ExtEngineManager::ResultSet::fetch(thread_db* tdbb)
|
||||
|
||||
|
||||
ExtEngineManager::Trigger::Trigger(thread_db* tdbb, MemoryPool& pool, ExtEngineManager* aExtManager,
|
||||
ExternalEngine* aEngine, RoutineMetadata* aMetadata, TriggerMessage& fieldsMsg,
|
||||
ExternalEngine* aEngine, RoutineMetadata* aMetadata,
|
||||
ExternalTrigger* aTrigger, const Jrd::Trigger* aTrg)
|
||||
: extManager(aExtManager),
|
||||
engine(aEngine),
|
||||
@ -487,121 +483,10 @@ ExtEngineManager::Trigger::Trigger(thread_db* tdbb, MemoryPool& pool, ExtEngineM
|
||||
|
||||
if (relation)
|
||||
{
|
||||
bool blrPresent = fieldsMsg.blr.hasData();
|
||||
Format* relFormat = relation->rel_current_format;
|
||||
GenericMap<Left<MetaName, USHORT> > fieldsMap;
|
||||
format = createFormat(pool, metadata->triggerFields);
|
||||
|
||||
for (size_t i = 0; i < relation->rel_fields->count(); ++i)
|
||||
{
|
||||
jrd_fld* field = (*relation->rel_fields)[i];
|
||||
if (!field)
|
||||
continue;
|
||||
|
||||
fieldsMap.put(field->fld_name, (USHORT) i);
|
||||
}
|
||||
|
||||
BlrReader reader(fieldsMsg.blr.begin(), fieldsMsg.blr.getCount());
|
||||
ULONG offset = 0;
|
||||
USHORT maxAlignment = 0;
|
||||
USHORT count;
|
||||
|
||||
if (blrPresent)
|
||||
{
|
||||
reader.checkByte(blr_version5);
|
||||
reader.checkByte(blr_begin);
|
||||
reader.checkByte(blr_message);
|
||||
reader.getByte(); // message number: ignore it
|
||||
count = reader.getWord();
|
||||
|
||||
if (count != 2 * fieldsMsg.names.getCount())
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_ee_blr_mismatch_names_count) <<
|
||||
Arg::Num(fieldsMsg.names.getCount()) <<
|
||||
Arg::Num(count));
|
||||
}
|
||||
}
|
||||
else
|
||||
count = fieldsMap.count() * 2;
|
||||
|
||||
format.reset(Format::newFormat(pool, count));
|
||||
|
||||
for (unsigned i = 0; i < count / 2; ++i)
|
||||
{
|
||||
dsc* desc = &format->fmt_desc[i * 2];
|
||||
|
||||
if (blrPresent)
|
||||
{
|
||||
USHORT pos;
|
||||
|
||||
if (!fieldsMap.get(fieldsMsg.names[i], pos))
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_ee_blr_mismatch_name_not_found) <<
|
||||
Arg::Str(fieldsMsg.names[i]));
|
||||
}
|
||||
|
||||
fieldsPos.add(pos);
|
||||
PAR_datatype(reader, desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldsPos.add(i);
|
||||
*desc = relFormat->fmt_desc[i];
|
||||
}
|
||||
|
||||
USHORT align = type_alignments[desc->dsc_dtype];
|
||||
maxAlignment = MAX(maxAlignment, align);
|
||||
|
||||
offset = FB_ALIGN(offset, align);
|
||||
desc->dsc_address = (UCHAR*) (IPTR) offset;
|
||||
offset += desc->dsc_length;
|
||||
|
||||
const dsc* fieldDesc = &relFormat->fmt_desc[i];
|
||||
|
||||
if (desc->isText() && desc->getCharSet() == CS_NONE)
|
||||
desc->setTextType(fieldDesc->getTextType());
|
||||
desc->setNullable(fieldDesc->isNullable());
|
||||
|
||||
++desc;
|
||||
|
||||
if (blrPresent)
|
||||
{
|
||||
PAR_datatype(reader, desc);
|
||||
|
||||
if (!DSC_EQUIV(desc, &shortDesc, false))
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_ee_blr_mismatch_null) <<
|
||||
Arg::Num(i * 2 + 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
*desc = shortDesc;
|
||||
|
||||
align = type_alignments[desc->dsc_dtype];
|
||||
maxAlignment = MAX(maxAlignment, align);
|
||||
|
||||
offset = FB_ALIGN(offset, align);
|
||||
desc->dsc_address = (UCHAR*) (IPTR) offset;
|
||||
offset += desc->dsc_length;
|
||||
}
|
||||
|
||||
if (blrPresent)
|
||||
{
|
||||
reader.checkByte(blr_end);
|
||||
reader.checkByte(blr_eoc);
|
||||
|
||||
if (offset != fieldsMsg.bufferLength)
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_ee_blr_mismatch_length) <<
|
||||
Arg::Num(fieldsMsg.bufferLength) <<
|
||||
Arg::Num(offset));
|
||||
}
|
||||
}
|
||||
|
||||
format->fmt_length = FB_ALIGN(offset, maxAlignment);
|
||||
for (unsigned i = 0; i < format->fmt_count / 2; ++i)
|
||||
fieldsPos.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -836,12 +721,12 @@ void ExtEngineManager::makeFunction(thread_db* tdbb, Jrd::Function* udf,
|
||||
LocalStatus status;
|
||||
|
||||
RefPtr<IMetadataBuilder> inBuilder(metadata->inputParameters->getBuilder(&status));
|
||||
inBuilder->release();
|
||||
status.check();
|
||||
inBuilder->release();
|
||||
|
||||
RefPtr<IMetadataBuilder> outBuilder(metadata->outputParameters->getBuilder(&status));
|
||||
outBuilder->release();
|
||||
status.check();
|
||||
outBuilder->release();
|
||||
|
||||
ExternalFunction* externalFunction;
|
||||
|
||||
@ -937,12 +822,12 @@ void ExtEngineManager::makeProcedure(thread_db* tdbb, jrd_prc* prc,
|
||||
LocalStatus status;
|
||||
|
||||
RefPtr<IMetadataBuilder> inBuilder(metadata->inputParameters->getBuilder(&status));
|
||||
inBuilder->release();
|
||||
status.check();
|
||||
inBuilder->release();
|
||||
|
||||
RefPtr<IMetadataBuilder> outBuilder(metadata->outputParameters->getBuilder(&status));
|
||||
outBuilder->release();
|
||||
status.check();
|
||||
outBuilder->release();
|
||||
|
||||
ExternalProcedure* externalProcedure;
|
||||
|
||||
@ -984,7 +869,7 @@ void ExtEngineManager::makeProcedure(thread_db* tdbb, jrd_prc* prc,
|
||||
}
|
||||
|
||||
|
||||
ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const Jrd::Trigger* trg,
|
||||
void ExtEngineManager::makeTrigger(thread_db* tdbb, Jrd::Trigger* trg,
|
||||
const MetaName& engine, const string& entryPoint, const string& body,
|
||||
ExternalTrigger::Type type)
|
||||
{
|
||||
@ -1031,10 +916,20 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
|
||||
item.length = sqlLen;
|
||||
item.scale = sqlScale;
|
||||
item.nullable = !field->fld_not_null;
|
||||
item.finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
TriggerMessage fieldsMsg(pool);
|
||||
LocalStatus status;
|
||||
|
||||
RefPtr<IMetadataBuilder> fieldsBuilder(relation ?
|
||||
metadata->triggerFields->getBuilder(&status) : NULL);
|
||||
if (relation)
|
||||
{
|
||||
status.check();
|
||||
fieldsBuilder->release();
|
||||
}
|
||||
|
||||
ExternalTrigger* externalTrigger;
|
||||
|
||||
{ // scope
|
||||
@ -1042,7 +937,7 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
|
||||
|
||||
LocalStatus status;
|
||||
externalTrigger = attInfo->engine->makeTrigger(&status, attInfo->context, metadata,
|
||||
&fieldsMsg);
|
||||
fieldsBuilder);
|
||||
status.check();
|
||||
|
||||
if (!externalTrigger)
|
||||
@ -1050,12 +945,18 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_eem_trig_not_returned) << trg->name << engine);
|
||||
}
|
||||
|
||||
if (relation)
|
||||
{
|
||||
metadata->triggerFields = fieldsBuilder->getMetadata(&status);
|
||||
status.check();
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return FB_NEW(getPool()) Trigger(tdbb, pool, this, attInfo->engine, metadata.release(),
|
||||
fieldsMsg, externalTrigger, trg);
|
||||
trg->extTrigger = FB_NEW(getPool()) Trigger(tdbb, pool, this, attInfo->engine,
|
||||
metadata.release(), externalTrigger, trg);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -52,35 +52,6 @@ struct impure_value;
|
||||
struct record_param;
|
||||
|
||||
|
||||
class TriggerMessage :
|
||||
public Firebird::VersionedIface<Firebird::ITriggerMessage, FB_TRIGGER_MESSAGE_VERSION>,
|
||||
public Firebird::PermanentStorage
|
||||
{
|
||||
public:
|
||||
explicit TriggerMessage(MemoryPool& pool)
|
||||
: PermanentStorage(pool),
|
||||
names(pool),
|
||||
blr(pool),
|
||||
bufferLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void FB_CARG set(const unsigned char* aBlr, unsigned aBlrLength, unsigned aBufferLength,
|
||||
const char** aNames, unsigned aCount)
|
||||
{
|
||||
blr.assign(aBlr, aBlrLength);
|
||||
bufferLength = aBufferLength;
|
||||
|
||||
for (unsigned i = 0; i < aCount; ++i)
|
||||
names.add(aNames[i]);
|
||||
}
|
||||
|
||||
public:
|
||||
Firebird::ObjectsArray<Firebird::string> names;
|
||||
Firebird::Array<UCHAR> blr;
|
||||
unsigned bufferLength;
|
||||
};
|
||||
|
||||
class ExtEngineManager : public Firebird::PermanentStorage
|
||||
{
|
||||
private:
|
||||
@ -136,7 +107,7 @@ private:
|
||||
return getMetadata(outputParameters);
|
||||
}
|
||||
|
||||
virtual Firebird::IMessageMetadata* FB_CARG getTriggerFields(
|
||||
virtual Firebird::IMessageMetadata* FB_CARG getTriggerMetadata(
|
||||
Firebird::IStatus* /*status*/) const
|
||||
{
|
||||
return getMetadata(triggerFields);
|
||||
@ -304,7 +275,7 @@ public:
|
||||
{
|
||||
public:
|
||||
Trigger(thread_db* tdbb, MemoryPool& pool, ExtEngineManager* aExtManager,
|
||||
Firebird::ExternalEngine* aEngine, RoutineMetadata* aMetadata, TriggerMessage& fieldsMsg,
|
||||
Firebird::ExternalEngine* aEngine, RoutineMetadata* aMetadata,
|
||||
Firebird::ExternalTrigger* aTrigger, const Jrd::Trigger* aTrg);
|
||||
~Trigger();
|
||||
|
||||
@ -346,7 +317,7 @@ public:
|
||||
void makeProcedure(thread_db* tdbb, jrd_prc* prc,
|
||||
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
|
||||
const Firebird::string& body);
|
||||
Trigger* makeTrigger(thread_db* tdbb, const Jrd::Trigger* trg,
|
||||
void makeTrigger(thread_db* tdbb, Jrd::Trigger* trg,
|
||||
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
|
||||
const Firebird::string& body, Firebird::ExternalTrigger::Type type);
|
||||
|
||||
|
@ -654,7 +654,7 @@ void Trigger::compile(thread_db* tdbb)
|
||||
if (extTrigger)
|
||||
return;
|
||||
|
||||
extTrigger = dbb->dbb_extManager.makeTrigger(tdbb, this, engine, entryPoint, extBody.c_str(),
|
||||
dbb->dbb_extManager.makeTrigger(tdbb, this, engine, entryPoint, extBody.c_str(),
|
||||
(relation ?
|
||||
(type & 1 ? ExternalTrigger::TYPE_BEFORE : ExternalTrigger::TYPE_AFTER) :
|
||||
Firebird::ExternalTrigger::TYPE_DATABASE));
|
||||
|
@ -157,7 +157,7 @@ public:
|
||||
virtual ExternalProcedure* FB_CALL makeProcedure(IStatus* status, ExternalContext* context,
|
||||
const IRoutineMetadata* metadata, IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder);
|
||||
virtual ExternalTrigger* FB_CALL makeTrigger(IStatus* status, ExternalContext* context,
|
||||
const IRoutineMetadata* metadata, ITriggerMessage* fieldsMsg);
|
||||
const IRoutineMetadata* metadata, IMetadataBuilder* fieldsBuilder);
|
||||
|
||||
public:
|
||||
virtual void FB_CALL dispose();
|
||||
@ -355,7 +355,7 @@ class SharedTrigger : public ExternalTrigger
|
||||
{
|
||||
public:
|
||||
SharedTrigger(IStatus* status, Engine* aEngine, ExternalContext* context,
|
||||
const IRoutineMetadata* aMetadata, ITriggerMessage* fieldsMsg)
|
||||
const IRoutineMetadata* aMetadata, IMetadataBuilder* fieldsBuilder)
|
||||
: engine(aEngine),
|
||||
metadata(aMetadata),
|
||||
moduleName(*getDefaultMemoryPool()),
|
||||
@ -365,7 +365,7 @@ public:
|
||||
{
|
||||
engine->loadModule(metadata, &moduleName, &entryPoint);
|
||||
TriggerNode* node = engine->findNode<TriggerNode>(registeredTriggers, moduleName, entryPoint);
|
||||
node->factory->setup(status, context, metadata, fieldsMsg);
|
||||
node->factory->setup(status, context, metadata, fieldsBuilder);
|
||||
}
|
||||
|
||||
virtual ~SharedTrigger()
|
||||
@ -715,11 +715,11 @@ ExternalProcedure* FB_CALL Engine::makeProcedure(IStatus* status, ExternalContex
|
||||
|
||||
|
||||
ExternalTrigger* FB_CALL Engine::makeTrigger(IStatus* status, ExternalContext* context,
|
||||
const IRoutineMetadata* metadata, ITriggerMessage* fieldsMsg)
|
||||
const IRoutineMetadata* metadata, IMetadataBuilder* fieldsBuilder)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new SharedTrigger(status, this, context, metadata, fieldsMsg);
|
||||
return new SharedTrigger(status, this, context, metadata, fieldsBuilder);
|
||||
}
|
||||
catch (const StatusException& e)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user