|
From: <asf...@us...> - 2013-01-29 01:21:36
|
Revision: 57629
http://sourceforge.net/p/firebird/code/57629
Author: asfernandes
Date: 2013-01-29 01:21:32 +0000 (Tue, 29 Jan 2013)
Log Message:
-----------
Migrate external triggers to the new message-based style.
Modified Paths:
--------------
firebird/trunk/examples/udr/UdrCppExample.cpp
firebird/trunk/lang_helpers/gds_codes.ftn
firebird/trunk/lang_helpers/gds_codes.pas
firebird/trunk/src/dsql/ExprNodes.cpp
firebird/trunk/src/include/firebird/ExternalEngine.h
firebird/trunk/src/include/firebird/Message.h
firebird/trunk/src/include/firebird/UdrCppEngine.h
firebird/trunk/src/include/firebird/UdrEngine.h
firebird/trunk/src/include/gen/codetext.h
firebird/trunk/src/include/gen/iberror.h
firebird/trunk/src/include/gen/msgs.h
firebird/trunk/src/include/gen/sql_code.h
firebird/trunk/src/include/gen/sql_state.h
firebird/trunk/src/jrd/ExtEngineManager.cpp
firebird/trunk/src/jrd/ExtEngineManager.h
firebird/trunk/src/jrd/Function.epp
firebird/trunk/src/jrd/dfw.epp
firebird/trunk/src/jrd/jrd.cpp
firebird/trunk/src/jrd/met.epp
firebird/trunk/src/jrd/met_proto.h
firebird/trunk/src/msgs/facilities2.sql
firebird/trunk/src/msgs/messages2.sql
firebird/trunk/src/msgs/system_errors2.sql
firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp
Modified: firebird/trunk/examples/udr/UdrCppExample.cpp
===================================================================
--- firebird/trunk/examples/udr/UdrCppExample.cpp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/examples/udr/UdrCppExample.cpp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -662,7 +662,7 @@
FB_UDR_BEGIN_PROCEDURE(gen_rows)
FB_UDR_EXECUTE_DYNAMIC_PROCEDURE
{
- MessageImpl inMessage(2, inMsg);
+ MessageImpl inMessage(2, in);
ParamDesc<ISC_LONG> startDesc(inMessage);
ParamDesc<ISC_LONG> endDesc(inMessage);
@@ -795,7 +795,6 @@
FB_UDR_END_PROCEDURE
-//// TODO: Rework triggers.
/***
Sample usage:
@@ -828,6 +827,11 @@
after insert on persons
external name 'udrcpp_example!replicate!ds1'
engine udr;
+
+create trigger persons_replicate2
+ after insert on persons
+ external name 'udrcpp_example!replicate_persons!ds1'
+ engine udr;
***/
FB_UDR_BEGIN_TRIGGER(replicate)
FB_UDR_TRIGGER(replicate)()
@@ -863,7 +867,7 @@
unsigned fieldsCount = fields->getCount(status);
ThrowError::check(status->get());
- MessageImpl message(fieldsCount, newMsg);
+ MessageImpl message(fieldsCount, newFields);
ISC_STATUS_ARRAY statusVector = {0};
isc_db_handle dbHandle = getIscDbHandle(context);
@@ -905,11 +909,11 @@
const char* table = metadata->getTriggerTable(status);
ThrowError::check(status->get());
- // Skip the first exclamation point, separing the module name and entry point.
+ // Skip the first exclamation point, separating the module name and entry point.
const char* info = strchr(metadata->getEntryPoint(status), '!');
ThrowError::check(status->get());
- // Skip the second exclamation point, separing the entry point and the misc info (config).
+ // Skip the second exclamation point, separating the entry point and the misc info (config).
if (info)
info = strchr(info + 1, '!');
@@ -1046,7 +1050,7 @@
break;
case SQL_FLOAT:
- var->sqltype = SQL_DOUBLE | (var->sqltype & 1);
+ var->sqltype = SQL_DOUBLE;
var->sqllen = sizeof(double);
// fall into
@@ -1069,8 +1073,7 @@
}
var->sqltype |= 1;
- var->sqlind = new short;
- *reinterpret_cast<short*>(var->sqlind) = -1;
+ var->sqlind = new short(-1);
}
delete [] outSqlDa->sqlvar[0].sqldata;
@@ -1083,3 +1086,151 @@
XSQLDA* inSqlDa;
isc_stmt_handle stmtHandle;
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;
+
+ delete [] reinterpret_cast<char*>(inSqlDa);
+
+ ISC_STATUS_ARRAY statusVector = {0};
+ isc_dsql_free_statement(statusVector, &stmtHandle, DSQL_drop);
+ }
+
+ FB_UDR_EXECUTE_MESSAGE_TRIGGER(
+ (FB_INTEGER, id, "ID")
+ (FB_VARCHAR(60 * 4), address, "ADDRESS")
+ (FB_VARCHAR(60 * 4), name, "NAME")
+ (FB_BLOB, info, "INFO")
+ )
+ {
+ inSqlDa->sqlvar[0].sqldata = reinterpret_cast<char*>(&newFields->id);
+ inSqlDa->sqlvar[0].sqlind = &newFields->idNull;
+
+ inSqlDa->sqlvar[1].sqldata = reinterpret_cast<char*>(&newFields->name.length);
+ inSqlDa->sqlvar[1].sqlind = &newFields->nameNull;
+
+ inSqlDa->sqlvar[2].sqldata = reinterpret_cast<char*>(&newFields->address.length);
+ inSqlDa->sqlvar[2].sqlind = &newFields->addressNull;
+
+ inSqlDa->sqlvar[3].sqldata = reinterpret_cast<char*>(&newFields->info);
+ inSqlDa->sqlvar[3].sqlind = &newFields->infoNull;
+
+ ISC_STATUS_ARRAY statusVector = {0};
+ isc_db_handle dbHandle = getIscDbHandle(context);
+ isc_tr_handle trHandle = getIscTrHandle(context);
+
+ ThrowError::check(isc_dsql_execute(statusVector, &trHandle, &stmtHandle, SQL_DIALECT_CURRENT,
+ inSqlDa), statusVector);
+ }
+
+ FB_UDR_INITIALIZE
+ {
+ ISC_STATUS_ARRAY statusVector = {0};
+ isc_db_handle dbHandle = getIscDbHandle(context);
+ isc_tr_handle trHandle = getIscTrHandle(context);
+
+ stmtHandle = 0;
+ ThrowError::check(isc_dsql_allocate_statement(statusVector, &dbHandle, &stmtHandle), statusVector);
+ ThrowError::check(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0,
+ "select data_source from replicate_config where name = ?",
+ SQL_DIALECT_CURRENT, NULL), statusVector);
+
+ AutoDispose<IStatus> status(master->getStatus());
+
+ const char* table = metadata->getTriggerTable(status);
+ ThrowError::check(status->get());
+
+ // Skip the first exclamation point, separating the module name and entry point.
+ const char* info = strchr(metadata->getEntryPoint(status), '!');
+ ThrowError::check(status->get());
+
+ // Skip the second exclamation point, separating the entry point and the misc info (config).
+ if (info)
+ info = strchr(info + 1, '!');
+
+ if (info)
+ ++info;
+ else
+ info = "";
+
+ inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
+ inSqlDa->version = SQLDA_VERSION1;
+ inSqlDa->sqln = 1;
+ ThrowError::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);
+
+ XSQLDA* outSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
+ outSqlDa->version = SQLDA_VERSION1;
+ outSqlDa->sqln = 1;
+ ThrowError::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';
+
+ ThrowError::check(isc_dsql_execute2(statusVector, &trHandle, &stmtHandle, SQL_DIALECT_CURRENT,
+ inSqlDa, outSqlDa), statusVector);
+ ThrowError::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);
+ ThrowError::check(status->get());
+
+ unsigned count = fields->getCount(status);
+ ThrowError::check(status->get());
+
+ char buffer[65536];
+ strcpy(buffer,
+ "execute block (\n"
+ " id type of column PERSONS.ID = ?,\n"
+ " name type of column PERSONS.NAME = ?,\n"
+ " address type of column PERSONS.ADDRESS = ?,\n"
+ " info type of column PERSONS.INFO = ?\n"
+ ")"
+ "as\n"
+ "begin\n"
+ " execute statement ('insert into persons (id, name, address, info)\n"
+ " values (?, ?, ?, ?)') (:id, :name, :address, :info)\n"
+ " on external data source '");
+ strcat(buffer, outSqlDa->sqlvar[0].sqldata + sizeof(short));
+ strcat(buffer, "';\nend");
+
+ ThrowError::check(isc_dsql_prepare(statusVector, &trHandle, &stmtHandle, 0, buffer,
+ SQL_DIALECT_CURRENT, NULL), statusVector);
+
+ inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(4))]);
+ inSqlDa->version = SQLDA_VERSION1;
+ inSqlDa->sqln = 4;
+ ThrowError::check(isc_dsql_describe_bind(statusVector, &stmtHandle, SQL_DIALECT_CURRENT, inSqlDa),
+ statusVector);
+
+ for (unsigned i = 0; i < 4; ++i)
+ {
+ XSQLVAR* var = &inSqlDa->sqlvar[i];
+ var->sqltype |= 1;
+ }
+
+ delete [] outSqlDa->sqlvar[0].sqldata;
+ delete [] reinterpret_cast<char*>(outSqlDa);
+
+ initialized = true;
+ }
+
+ bool initialized;
+ XSQLDA* inSqlDa;
+ isc_stmt_handle stmtHandle;
+FB_UDR_END_TRIGGER
Modified: firebird/trunk/lang_helpers/gds_codes.ftn
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.ftn 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/lang_helpers/gds_codes.ftn 2013-01-29 01:21:32 UTC (rev 57629)
@@ -1504,6 +1504,10 @@
PARAMETER (GDS__null_spb = 335545045)
INTEGER*4 GDS__max_args_exceeded
PARAMETER (GDS__max_args_exceeded = 335545046)
+ INTEGER*4 GDS__ee_blr_mismatch_names_count
+ PARAMETER (GDS__ee_blr_mismatch_names_count = 335545047)
+ INTEGER*4 GDS__ee_blr_mismatch_name_not_found
+ PARAMETER (GDS__ee_blr_mismatch_name_not_found = 335545048)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw
Modified: firebird/trunk/lang_helpers/gds_codes.pas
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.pas 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/lang_helpers/gds_codes.pas 2013-01-29 01:21:32 UTC (rev 57629)
@@ -759,6 +759,8 @@
gds_no_providers = 335545044;
gds_null_spb = 335545045;
gds_max_args_exceeded = 335545046;
+ gds_ee_blr_mismatch_names_count = 335545047;
+ gds_ee_blr_mismatch_name_not_found = 335545048;
gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932;
Modified: firebird/trunk/src/dsql/ExprNodes.cpp
===================================================================
--- firebird/trunk/src/dsql/ExprNodes.cpp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/dsql/ExprNodes.cpp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -10764,11 +10764,11 @@
dsc* const srcDesc = EVL_expr(tdbb, request, *sourcePtr);
if (srcDesc && !(request->req_flags & req_null))
{
- *nullPtr = FALSE;
+ *nullPtr = 0;
MOV_move(tdbb, srcDesc, &argDesc);
}
else
- *nullPtr = TRUE;
+ *nullPtr = -1;
}
}
Modified: firebird/trunk/src/include/firebird/ExternalEngine.h
===================================================================
--- firebird/trunk/src/include/firebird/ExternalEngine.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/firebird/ExternalEngine.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -38,14 +38,23 @@
class ExternalEngine;
-struct BlrMessage
+class IRoutineMessage : public IVersioned
{
- const unsigned char* blr;
- unsigned int blrLength;
- unsigned int bufferLength;
+public:
+ virtual void FB_CARG set(const unsigned char* blr, unsigned blrLength, unsigned bufferLength) = 0;
};
+#define FB_ROUTINE_MESSAGE_VERSION (FB_VERSIONED_VERSION + 1)
+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
@@ -193,11 +202,11 @@
// Called when engine wants to load object in the cache. Objects are disposed when
// going out of the cache.
virtual ExternalFunction* FB_CALL makeFunction(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata, BlrMessage* inBlr, BlrMessage* outBlr) = 0;
+ const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg) = 0;
virtual ExternalProcedure* FB_CALL makeProcedure(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata, BlrMessage* inBlr, BlrMessage* outBlr) = 0;
+ const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg) = 0;
virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata) = 0;
+ const IRoutineMetadata* metadata, ITriggerMessage* triggerMsg) = 0;
};
#define FB_EXTERNAL_ENGINE_VERSION (FB_PLUGIN_VERSION + 6)
Modified: firebird/trunk/src/include/firebird/Message.h
===================================================================
--- firebird/trunk/src/include/firebird/Message.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/firebird/Message.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -30,54 +30,66 @@
#include <string.h>
#define FB_MESSAGE(name, fields) \
- FB_MESSAGE_I(name, FB_BOOST_PP_CAT(FB_MESSAGE_X fields, 0))
+ struct name \
+ { \
+ FB_MESSAGE_I(name, 2, FB_BOOST_PP_CAT(FB_MESSAGE_X fields, 0)) \
+ }
#define FB_MESSAGE_X(x, y) ((x, y)) FB_MESSAGE_Y
#define FB_MESSAGE_Y(x, y) ((x, y)) FB_MESSAGE_X
#define FB_MESSAGE_X0
#define FB_MESSAGE_Y0
-#define FB_MESSAGE_I(name, fields) \
+#define FB_TRIGGER_MESSAGE(name, fields) \
struct name \
{ \
- static const unsigned char* getBlr(unsigned* length) \
- { \
- static const unsigned char blr[] = { \
- blr_version5, \
- blr_begin, \
- blr_message, 0, \
- (2 * (FB_BOOST_PP_SEQ_SIZE(fields))) & 0xFF, \
- (2 * (FB_BOOST_PP_SEQ_SIZE(fields))) >> 8, \
- FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_BLR, _, fields) \
- blr_end, \
- blr_eoc \
- }; \
- *length = sizeof(blr); \
- return blr; \
- } \
- \
- static unsigned getSize() \
- { \
- return (unsigned)(size_t) (&((name*) 0)->FB_BOOST_PP_CAT( \
- FB_BOOST_PP_TUPLE_ELEM(2, 1, \
- FB_BOOST_PP_SEQ_ELEM(FB_BOOST_PP_DEC(FB_BOOST_PP_SEQ_SIZE(fields)), fields)), \
- Null) - 0) + sizeof(ISC_SHORT); \
- } \
- \
- void clear() \
- { \
- memset(this, 0, sizeof(*this)); \
- } \
- \
- FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_FIELD, _, fields) \
+ FB_MESSAGE_I(name, 3, FB_BOOST_PP_CAT(FB_TRIGGER_MESSAGE_X fields, 0)) \
+ FB_TRIGGER_MESSAGE_NAMES_I(name, 3, FB_BOOST_PP_CAT(FB_TRIGGER_MESSAGE_NAMES_X fields, 0)) \
}
+#define FB_TRIGGER_MESSAGE_X(x, y, z) ((x, y, z)) FB_TRIGGER_MESSAGE_Y
+#define FB_TRIGGER_MESSAGE_Y(x, y, z) ((x, y, z)) FB_TRIGGER_MESSAGE_X
+#define FB_TRIGGER_MESSAGE_X0
+#define FB_TRIGGER_MESSAGE_Y0
+
+#define FB_MESSAGE_I(name, size, fields) \
+ static const unsigned char* getBlr(unsigned* length) \
+ { \
+ static const unsigned char blr[] = { \
+ blr_version5, \
+ blr_begin, \
+ blr_message, 0, \
+ (2 * (FB_BOOST_PP_SEQ_SIZE(fields))) & 0xFF, \
+ (2 * (FB_BOOST_PP_SEQ_SIZE(fields))) >> 8, \
+ FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_BLR, size, fields) \
+ blr_end, \
+ blr_eoc \
+ }; \
+ *length = sizeof(blr); \
+ return blr; \
+ } \
+ \
+ static unsigned getSize() \
+ { \
+ return (unsigned)(size_t) (&((name*) 0)->FB_BOOST_PP_CAT( \
+ FB_BOOST_PP_TUPLE_ELEM(size, 1, \
+ FB_BOOST_PP_SEQ_ELEM(FB_BOOST_PP_DEC(FB_BOOST_PP_SEQ_SIZE(fields)), fields)), \
+ Null) - 0) + sizeof(ISC_SHORT); \
+ } \
+ \
+ void clear() \
+ { \
+ memset(this, 0, sizeof(*this)); \
+ } \
+ \
+ FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_FIELD, size, fields)
+
#define FB_MESSAGE_FIELD(r, _, i, xy) \
- FB_BOOST_PP_CAT(FB_TYPE_, FB_BOOST_PP_TUPLE_ELEM(2, 0, xy)) FB_BOOST_PP_TUPLE_ELEM(2, 1, xy); \
- ISC_SHORT FB_BOOST_PP_CAT(FB_BOOST_PP_TUPLE_ELEM(2, 1, xy), Null);
+ FB_BOOST_PP_CAT(FB_TYPE_, FB_BOOST_PP_TUPLE_ELEM(_, 0, xy)) FB_BOOST_PP_TUPLE_ELEM(_, 1, xy); \
+ ISC_SHORT FB_BOOST_PP_CAT(FB_BOOST_PP_TUPLE_ELEM(_, 1, xy), Null);
#define FB_MESSAGE_BLR(r, _, i, xy) \
- FB_BOOST_PP_CAT(FB_BLR_, FB_BOOST_PP_TUPLE_ELEM(2, 0, xy)), \
+ FB_BOOST_PP_CAT(FB_BLR_, FB_BOOST_PP_TUPLE_ELEM(_, 0, xy)), \
FB_BLR_FB_SMALLINT,
#define FB_BLR_FB_SCALED_SMALLINT(scale) blr_short, (scale)
@@ -126,7 +138,45 @@
} \
}
+#define FB_TRIGGER_MESSAGE_DESC(name, fields) \
+ FB_TRIGGER_MESSAGE(name, fields); \
+ struct name##Desc : public name \
+ { \
+ ::Firebird::FbMessage desc; \
+ \
+ name##Desc() \
+ { \
+ desc.blr = getBlr(&desc.blrLength); \
+ desc.buffer = (unsigned char*) this; \
+ desc.bufferLength = getSize(); \
+ } \
+ }
+#define FB_TRIGGER_MESSAGE_NAMES(name, fields) \
+ FB_TRIGGER_MESSAGE_NAMES_I(name, 3, FB_BOOST_PP_CAT(FB_TRIGGER_MESSAGE_NAMES_X fields, 0))
+
+#define FB_TRIGGER_MESSAGE_NAMES_X(x, y, z) ((x, y, z)) FB_TRIGGER_MESSAGE_NAMES_Y
+#define FB_TRIGGER_MESSAGE_NAMES_Y(x, y, z) ((x, y, z)) FB_TRIGGER_MESSAGE_NAMES_X
+#define FB_TRIGGER_MESSAGE_NAMES_X0
+#define FB_TRIGGER_MESSAGE_NAMES_Y0
+
+#define FB_TRIGGER_MESSAGE_NAMES_I(name, size, fields) \
+ static const char** getNames(unsigned* count) \
+ { \
+ *count = FB_BOOST_PP_SEQ_SIZE(fields); \
+ \
+ static const char* names[] = { \
+ FB_BOOST_PP_SEQ_FOR_EACH_I(FB_TRIGGER_MESSAGE_NAME, size, fields) \
+ NULL \
+ }; \
+ \
+ return names; \
+ }
+
+#define FB_TRIGGER_MESSAGE_NAME(r, _, i, xy) \
+ FB_BOOST_PP_TUPLE_ELEM(_, 2, xy),
+
+
namespace Firebird {
Modified: firebird/trunk/src/include/firebird/UdrCppEngine.h
===================================================================
--- firebird/trunk/src/include/firebird/UdrCppEngine.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/firebird/UdrCppEngine.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -86,11 +86,11 @@
#define FB_UDR_EXECUTE__FUNCTION \
virtual void FB_CALL execute(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
- void* inMsg, void* outMsg) \
+ void* in, void* out) \
{ \
try \
{ \
- internalExecute(error, context, (InMessage*) inMsg, (OutMessage*) outMsg); \
+ internalExecute(error, context, (InMessage*) in, (OutMessage*) out); \
} \
FB_UDR__CATCH \
} \
@@ -151,11 +151,11 @@
#define FB_UDR_EXECUTE__PROCEDURE \
virtual ::Firebird::ExternalResultSet* FB_CALL open(::Firebird::Error* error, \
- ::Firebird::ExternalContext* context, void* inMsg, void* outMsg) \
+ ::Firebird::ExternalContext* context, void* in, void* out) \
{ \
try \
{ \
- return new ResultSet(error, context, this, (InMessage*) inMsg, (OutMessage*) outMsg); \
+ return new ResultSet(error, context, this, (InMessage*) in, (OutMessage*) out); \
} \
FB_UDR__CATCH \
\
@@ -166,9 +166,9 @@
{ \
public: \
ResultSet(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
- This* procedure, InMessage* inMsg, OutMessage* outMsg) \
+ This* const procedure, InMessage* const in, OutMessage* const out) \
: ::Firebird::Udr::ResultSet<ResultSet, This, InMessage, OutMessage>( \
- context, procedure, inMsg, outMsg)
+ context, procedure, in, out)
#define FB_UDR_FETCH_PROCEDURE \
virtual bool FB_CALL fetch(::Firebird::Error* error) \
@@ -202,21 +202,30 @@
};
#define FB_UDR_EXECUTE_DYNAMIC_TRIGGER \
+ typedef void* 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 \
virtual void FB_CALL execute(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
- ::Firebird::ExternalTrigger::Action action, void* oldMsg, void* newMsg) \
+ ::Firebird::ExternalTrigger::Action action, void* oldFields, void* newFields) \
{ \
try \
{ \
- internalExecute(error, context, action, oldMsg, newMsg); \
+ internalExecute(error, context, action, (FieldsMessage*) oldFields, (FieldsMessage*) newFields); \
} \
FB_UDR__CATCH \
} \
\
void internalExecute(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
- ::Firebird::ExternalTrigger::Action action, void* oldMsg, void* newMsg)
+ ::Firebird::ExternalTrigger::Action action, FieldsMessage* oldFields, FieldsMessage* newFields)
#define FB_UDR_INITIALIZE \
@@ -499,10 +508,10 @@
}
protected:
- Firebird::ExternalContext* context;
- Procedure* procedure;
- InMessage* in;
- OutMessage* out;
+ Firebird::ExternalContext* const context;
+ Procedure* const procedure;
+ InMessage* const in;
+ OutMessage* const out;
};
@@ -620,10 +629,10 @@
}
virtual void setup(Error* /*error*/, ExternalContext* /*context*/,
- const IRoutineMetadata* /*metadata*/, BlrMessage* inBlr, BlrMessage* outBlr)
+ const IRoutineMetadata* /*metadata*/, IRoutineMessage* in, IRoutineMessage* out)
{
- setBlr(inBlr, (typename T::InMessage*) 0);
- setBlr(outBlr, (typename T::OutMessage*) 0);
+ setBlr(in, (typename T::InMessage*) 0);
+ setBlr(out, (typename T::OutMessage*) 0);
}
virtual ExternalFunction* FB_CALL newItem(Error* error, ExternalContext* context,
@@ -635,13 +644,14 @@
}
private:
- template <typename MessageType> void setBlr(BlrMessage* blrMessage, MessageType*)
+ template <typename MessageType> void setBlr(IRoutineMessage* blrMessage, MessageType*)
{
- blrMessage->blr = MessageType::getBlr(&blrMessage->blrLength);
- blrMessage->bufferLength = MessageType::getSize();
+ unsigned blrLength;
+ const unsigned char* blr = MessageType::getBlr(&blrLength);
+ blrMessage->set(blr, blrLength, MessageType::getSize());
}
- void setBlr(BlrMessage* blrMessage, void**)
+ void setBlr(IRoutineMessage* /*blrMessage*/, void**)
{
}
};
@@ -656,10 +666,10 @@
}
virtual void setup(Error* /*error*/, ExternalContext* /*context*/,
- const IRoutineMetadata* /*metadata*/, BlrMessage* inBlr, BlrMessage* outBlr)
+ const IRoutineMetadata* /*metadata*/, IRoutineMessage* in, IRoutineMessage* out)
{
- setBlr(inBlr, (typename T::InMessage*) 0);
- setBlr(outBlr, (typename T::OutMessage*) 0);
+ setBlr(in, (typename T::InMessage*) 0);
+ setBlr(out, (typename T::OutMessage*) 0);
}
virtual ExternalProcedure* FB_CALL newItem(Error* error, ExternalContext* context,
@@ -671,13 +681,14 @@
}
private:
- template <typename MessageType> void setBlr(BlrMessage* blrMessage, MessageType*)
+ template <typename MessageType> void setBlr(IRoutineMessage* blrMessage, MessageType*)
{
- blrMessage->blr = MessageType::getBlr(&blrMessage->blrLength);
- blrMessage->bufferLength = MessageType::getSize();
+ unsigned blrLength;
+ const unsigned char* blr = MessageType::getBlr(&blrLength);
+ blrMessage->set(blr, blrLength, MessageType::getSize());
}
- void setBlr(BlrMessage* blrMessage, void**)
+ void setBlr(IRoutineMessage* /*blrMessage*/, void**)
{
}
};
@@ -692,8 +703,9 @@
}
virtual void setup(Error* /*error*/, ExternalContext* /*context*/,
- const IRoutineMetadata* /*metadata*/)
+ const IRoutineMetadata* /*metadata*/, ITriggerMessage* fields)
{
+ setBlr(fields, (typename T::FieldsMessage*) 0);
}
virtual ExternalTrigger* FB_CALL newItem(Error* error, ExternalContext* context,
@@ -703,6 +715,20 @@
obj->initialize(error, context);
return obj;
}
+
+private:
+ template <typename MessageType> void setBlr(ITriggerMessage* blrMessage, MessageType*)
+ {
+ unsigned blrLength, namesCount;
+ const unsigned char* blr = MessageType::getBlr(&blrLength);
+ const char** names = MessageType::getNames(&namesCount);
+
+ blrMessage->set(blr, blrLength, MessageType::getSize(), names, namesCount);
+ }
+
+ void setBlr(ITriggerMessage* /*blrMessage*/, void**)
+ {
+ }
};
Modified: firebird/trunk/src/include/firebird/UdrEngine.h
===================================================================
--- firebird/trunk/src/include/firebird/UdrEngine.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/firebird/UdrEngine.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -40,7 +40,7 @@
{
public:
virtual void setup(Error* error, ExternalContext* context, const IRoutineMetadata* metadata,
- BlrMessage* inBlr, BlrMessage* outBlr) = 0;
+ IRoutineMessage* in, IRoutineMessage* out) = 0;
virtual ExternalFunction* FB_CALL newItem(Error* error, ExternalContext* context,
const IRoutineMetadata* metadata) = 0;
};
@@ -49,7 +49,7 @@
{
public:
virtual void setup(Error* error, ExternalContext* context, const IRoutineMetadata* metadata,
- BlrMessage* inBlr, BlrMessage* outBlr) = 0;
+ IRoutineMessage* in, IRoutineMessage* out) = 0;
virtual ExternalProcedure* FB_CALL newItem(Error* error, ExternalContext* context,
const IRoutineMetadata* metadata) = 0;
};
@@ -57,7 +57,8 @@
class TriggerFactory
{
public:
- virtual void setup(Error* error, ExternalContext* context, const IRoutineMetadata* metadata) = 0;
+ virtual void setup(Error* error, ExternalContext* context, const IRoutineMetadata* metadata,
+ ITriggerMessage* fields) = 0;
virtual ExternalTrigger* FB_CALL newItem(Error* error, ExternalContext* context,
const IRoutineMetadata* metadata) = 0;
};
Modified: firebird/trunk/src/include/gen/codetext.h
===================================================================
--- firebird/trunk/src/include/gen/codetext.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/gen/codetext.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -748,6 +748,8 @@
{"no_providers", 335545044},
{"null_spb", 335545045},
{"max_args_exceeded", 335545046},
+ {"ee_blr_mismatch_names_count", 335545047},
+ {"ee_blr_mismatch_name_not_found", 335545048},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},
Modified: firebird/trunk/src/include/gen/iberror.h
===================================================================
--- firebird/trunk/src/include/gen/iberror.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/gen/iberror.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -782,6 +782,8 @@
const ISC_STATUS isc_no_providers = 335545044L;
const ISC_STATUS isc_null_spb = 335545045L;
const ISC_STATUS isc_max_args_exceeded = 335545046L;
+const ISC_STATUS isc_ee_blr_mismatch_names_count = 335545047L;
+const ISC_STATUS isc_ee_blr_mismatch_name_not_found = 335545048L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@@ -1226,7 +1228,7 @@
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
-const ISC_STATUS isc_err_max = 1170;
+const ISC_STATUS isc_err_max = 1172;
#else /* c definitions */
@@ -1978,6 +1980,8 @@
#define isc_no_providers 335545044L
#define isc_null_spb 335545045L
#define isc_max_args_exceeded 335545046L
+#define isc_ee_blr_mismatch_names_count 335545047L
+#define isc_ee_blr_mismatch_name_not_found 335545048L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@@ -2422,7 +2426,7 @@
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
-#define isc_err_max 1170
+#define isc_err_max 1172
#endif
Modified: firebird/trunk/src/include/gen/msgs.h
===================================================================
--- firebird/trunk/src/include/gen/msgs.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/gen/msgs.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -751,6 +751,8 @@
{335545044, "No providers loaded"}, /* no_providers */
{335545045, "NULL data with non-zero SPB length"}, /* null_spb */
{335545046, "Maximum (@1) number of arguments exceeded for function @2"}, /* max_args_exceeded */
+ {335545047, "External BLR message mismatch: names count = @1, blr count = @2"}, /* ee_blr_mismatch_names_count */
+ {335545048, "External BLR message mismatch: name @1 not found"}, /* ee_blr_mismatch_name_not_found */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
Modified: firebird/trunk/src/include/gen/sql_code.h
===================================================================
--- firebird/trunk/src/include/gen/sql_code.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/gen/sql_code.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -747,6 +747,8 @@
{335545044, -902}, /* 724 no_providers */
{335545045, -104}, /* 725 null_spb */
{335545046, -833}, /* 726 max_args_exceeded */
+ {335545047, -901}, /* 727 ee_blr_mismatch_names_count */
+ {335545048, -901}, /* 728 ee_blr_mismatch_name_not_found */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */
Modified: firebird/trunk/src/include/gen/sql_state.h
===================================================================
--- firebird/trunk/src/include/gen/sql_state.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/include/gen/sql_state.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -747,6 +747,8 @@
{335545044, "39000"}, // 724 no_providers
{335545045, "42818"}, // 725 null_spb
{335545046, "42000"}, // 726 max_args_exceeded
+ {335545047, "42000"}, // 727 ee_blr_mismatch_names_count
+ {335545048, "42000"}, // 728 ee_blr_mismatch_name_not_found
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw
Modified: firebird/trunk/src/jrd/ExtEngineManager.cpp
===================================================================
--- firebird/trunk/src/jrd/ExtEngineManager.cpp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/jrd/ExtEngineManager.cpp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -41,6 +41,7 @@
#include "../jrd/intl_proto.h"
#include "../jrd/met_proto.h"
#include "../jrd/mov_proto.h"
+#include "../jrd/par_proto.h"
#include "../jrd/thread_proto.h"
#include "../jrd/Function.h"
#include "../common/isc_proto.h"
@@ -408,16 +409,140 @@
//---------------------
-ExtEngineManager::Trigger::Trigger(thread_db* tdbb, ExtEngineManager* aExtManager,
- ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalTrigger* aTrigger,
- const Jrd::Trigger* aTrg)
+ExtEngineManager::Trigger::Trigger(thread_db* tdbb, MemoryPool& pool, ExtEngineManager* aExtManager,
+ ExternalEngine* aEngine, RoutineMetadata* aMetadata, TriggerMessage& fieldsMsg,
+ ExternalTrigger* aTrigger, const Jrd::Trigger* aTrg)
: extManager(aExtManager),
engine(aEngine),
metadata(aMetadata),
trigger(aTrigger),
trg(aTrg),
+ fieldsPos(pool),
database(tdbb->getDatabase())
{
+ dsc shortDesc;
+ shortDesc.makeShort(0);
+
+ jrd_rel* relation = trg->relation;
+
+ if (relation)
+ {
+ bool blrPresent = fieldsMsg.blr.hasData();
+ Format* relFormat = relation->rel_current_format;
+ GenericMap<Left<MetaName, USHORT> > fieldsMap;
+
+ 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(tdbb, 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*) 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(tdbb, 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*) 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);
+ }
}
@@ -444,85 +569,73 @@
if (newRpb)
setValues(tdbb, newMsg, newRpb);
- Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
+ { // scope
+ Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
- trigger->execute(RaiseError(), attInfo->context, action,
- (oldRpb ? oldMsg.begin() : NULL), (newRpb ? newMsg.begin() : NULL));
+ trigger->execute(RaiseError(), attInfo->context, action,
+ (oldRpb ? oldMsg.begin() : NULL), (newRpb ? newMsg.begin() : NULL));
+ }
if (newRpb)
{
+ // Move data back from the message to the record.
+
Record* record = newRpb->rpb_record;
- const Format* format = record->rec_format;
- const UCHAR* msg = newMsg.begin();
- unsigned pos = 0;
+ UCHAR* p = newMsg.begin();
- for (unsigned i = 0; i < format->fmt_count; ++i)
+ for (unsigned i = 0; i < format->fmt_count / 2; ++i)
{
- if (format->fmt_desc[i].dsc_dtype == dtype_unknown)
- continue;
+ USHORT fieldPos = fieldsPos[i];
- dsc desc;
- bool readonly = !EVL_field(newRpb->rpb_relation, record, i, &desc) &&
- desc.dsc_address && !(desc.dsc_flags & DSC_null);
+ dsc target;
+ bool readonly = !EVL_field(newRpb->rpb_relation, record, fieldPos, &target) &&
+ target.dsc_address && !(target.dsc_flags & DSC_null);
- unsigned align = type_alignments[desc.dsc_dtype];
- if (align)
- pos = FB_ALIGN(pos, align);
-
- const unsigned dataPos = pos;
- pos += desc.dsc_length;
-
- align = type_alignments[dtype_short];
- if (align)
- pos = FB_ALIGN(pos, align);
-
if (!readonly)
{
- if (*(USHORT*) &msg[pos])
- SET_NULL(record, i);
- else
+ SSHORT* nullSource = (SSHORT*) (p + (IPTR) format->fmt_desc[i * 2 + 1].dsc_address);
+
+ if (*nullSource == 0)
{
- memcpy(desc.dsc_address, msg + dataPos, desc.dsc_length);
- CLEAR_NULL(record, i);
+ dsc source = format->fmt_desc[i * 2];
+ source.dsc_address += (IPTR) p;
+ MOV_move(tdbb, &source, &target);
+ CLEAR_NULL(record, fieldPos);
}
+ else
+ SET_NULL(record, fieldPos);
}
-
- pos += sizeof(USHORT);
}
}
}
-void ExtEngineManager::Trigger::setValues(thread_db* /*tdbb*/, Array<UCHAR>& msgBuffer,
+void ExtEngineManager::Trigger::setValues(thread_db* tdbb, Array<UCHAR>& msgBuffer,
record_param* rpb) const
{
if (!rpb || !rpb->rpb_record)
return;
- Record* record = rpb->rpb_record;
- const Format* format = record->rec_format;
+ UCHAR* p = msgBuffer.getBuffer(format->fmt_length);
+ ///memset(p, 0, format->fmt_length);
- for (unsigned i = 0; i < format->fmt_count; ++i)
+ for (unsigned i = 0; i < format->fmt_count / 2; ++i)
{
- if (format->fmt_desc[i].dsc_dtype == dtype_unknown)
- continue;
+ USHORT fieldPos = fieldsPos[i];
- dsc desc;
- EVL_field(rpb->rpb_relation, record, i, &desc);
+ dsc source;
+ EVL_field(rpb->rpb_relation, rpb->rpb_record, fieldPos, &source);
// CVC: I'm not sure why it's not important to check EVL_field's result.
- unsigned align = type_alignments[desc.dsc_dtype];
- if (align)
- msgBuffer.resize(FB_ALIGN(msgBuffer.getCount(), align));
+ SSHORT* nullTarget = (SSHORT*) (p + (IPTR) format->fmt_desc[i * 2 + 1].dsc_address);
+ *nullTarget = (source.dsc_flags & DSC_null) != 0 ? -1 : 0;
- msgBuffer.add(desc.dsc_address, desc.dsc_length);
-
- align = type_alignments[dtype_short];
- if (align)
- msgBuffer.resize(FB_ALIGN(msgBuffer.getCount(), align));
-
- USHORT nullFlag = (desc.dsc_flags & DSC_null) != 0;
- msgBuffer.add((UCHAR*) &nullFlag, sizeof(nullFlag));
+ if (*nullTarget == 0)
+ {
+ dsc target = format->fmt_desc[i * 2];
+ target.dsc_address += (IPTR) p;
+ MOV_move(tdbb, &source, &target);
+ }
}
}
@@ -598,7 +711,7 @@
ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, const Jrd::Function* udf,
const MetaName& engine, const string& entryPoint, const string& body,
- BlrMessage* inBlr, BlrMessage* outBlr)
+ RoutineMessage* inMsg, RoutineMessage* outMsg)
{
string entryPointTrimmed = entryPoint;
entryPointTrimmed.trim();
@@ -657,7 +770,7 @@
Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
externalFunction = attInfo->engine->makeFunction(RaiseError(), attInfo->context, metadata,
- inBlr, outBlr);
+ inMsg, outMsg);
if (!externalFunction)
{
@@ -683,7 +796,7 @@
ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, const jrd_prc* prc,
const MetaName& engine, const string& entryPoint, const string& body,
- BlrMessage* inBlr, BlrMessage* outBlr)
+ RoutineMessage* inMsg, RoutineMessage* outMsg)
{
string entryPointTrimmed = entryPoint;
entryPointTrimmed.trim();
@@ -736,7 +849,7 @@
Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
externalProcedure = attInfo->engine->makeProcedure(RaiseError(), attInfo->context, metadata,
- inBlr, outBlr);
+ inMsg, outMsg);
if (!externalProcedure)
{
@@ -761,7 +874,8 @@
ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const Jrd::Trigger* trg,
- const MetaName& engine, const string& entryPoint, const string& body, ExternalTrigger::Type type)
+ const MetaName& engine, const string& entryPoint, const string& body,
+ ExternalTrigger::Type type)
{
string entryPointTrimmed = entryPoint;
entryPointTrimmed.trim();
@@ -807,12 +921,14 @@
}
}
+ TriggerMessage fieldsMsg(pool);
ExternalTrigger* externalTrigger;
{ // scope
Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
- externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context, metadata);
+ externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context, metadata,
+ &fieldsMsg);
if (!externalTrigger)
{
@@ -823,8 +939,8 @@
try
{
- return FB_NEW(getPool()) Trigger(tdbb, this, attInfo->engine, metadata.release(),
- externalTrigger, trg);
+ return FB_NEW(getPool()) Trigger(tdbb, pool, this, attInfo->engine, metadata.release(),
+ fieldsMsg, externalTrigger, trg);
}
catch (...)
{
Modified: firebird/trunk/src/jrd/ExtEngineManager.h
===================================================================
--- firebird/trunk/src/jrd/ExtEngineManager.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/jrd/ExtEngineManager.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -52,6 +52,58 @@
struct record_param;
+class RoutineMessage :
+ public Firebird::VersionedIface<Firebird::IRoutineMessage, FB_ROUTINE_MESSAGE_VERSION>,
+ public Firebird::PermanentStorage
+{
+public:
+ explicit RoutineMessage(MemoryPool& pool)
+ : PermanentStorage(pool),
+ blr(pool),
+ bufferLength(0)
+ {
+ }
+
+ virtual void FB_CARG set(const unsigned char* aBlr, unsigned aBlrLength, unsigned aBufferLength)
+ {
+ blr.assign(aBlr, aBlrLength);
+ bufferLength = aBufferLength;
+ }
+
+public:
+ Firebird::Array<UCHAR> blr;
+ unsigned bufferLength;
+};
+
+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:
@@ -59,8 +111,9 @@
template <typename T> class ContextManager;
class TransactionImpl;
- class RoutineMetadata : public Firebird::VersionedIface<Firebird::IRoutineMetadata, FB_ROUTINE_METADATA_VERSION>,
- public Firebird::PermanentStorage
+ class RoutineMetadata :
+ public Firebird::VersionedIface<Firebird::IRoutineMetadata, FB_ROUTINE_METADATA_VERSION>,
+ public Firebird::PermanentStorage
{
public:
explicit RoutineMetadata(MemoryPool& pool)
@@ -264,11 +317,9 @@
class Trigger
{
public:
- Trigger(thread_db* tdbb, ExtEngineManager* aExtManager,
- Firebird::ExternalEngine* aEngine,
- RoutineMetadata* aMetadata,
- Firebird::ExternalTrigger* aTrigger,
- const Jrd::Trigger* aTrg);
+ Trigger(thread_db* tdbb, MemoryPool& pool, ExtEngineManager* aExtManager,
+ Firebird::ExternalEngine* aEngine, RoutineMetadata* aMetadata, TriggerMessage& fieldsMsg,
+ Firebird::ExternalTrigger* aTrigger, const Jrd::Trigger* aTrg);
~Trigger();
void execute(thread_db* tdbb, Firebird::ExternalTrigger::Action action,
@@ -280,8 +331,10 @@
ExtEngineManager* extManager;
Firebird::ExternalEngine* engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
+ Firebird::AutoPtr<Format> format;
Firebird::ExternalTrigger* trigger;
const Jrd::Trigger* trg;
+ Firebird::Array<USHORT> fieldsPos;
Database* database;
};
@@ -303,10 +356,10 @@
Function* makeFunction(thread_db* tdbb, const Jrd::Function* udf,
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
- const Firebird::string& body, Firebird::BlrMessage* inBlr, Firebird::BlrMessage* outBlr);
+ const Firebird::string& body, RoutineMessage* inMsg, RoutineMessage* outMsg);
Procedure* makeProcedure(thread_db* tdbb, const jrd_prc* prc,
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
- const Firebird::string& body, Firebird::BlrMessage* inBlr, Firebird::BlrMessage* outBlr);
+ const Firebird::string& body, RoutineMessage* inMsg, RoutineMessage* outMsg);
Trigger* makeTrigger(thread_db* tdbb, const Jrd::Trigger* trg,
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
const Firebird::string& body, Firebird::ExternalTrigger::Type type);
Modified: firebird/trunk/src/jrd/Function.epp
===================================================================
--- firebird/trunk/src/jrd/Function.epp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/jrd/Function.epp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -374,16 +374,9 @@
function->fun_external = NULL;
function->setStatement(NULL);
- BlrMessage inBlr;
- inBlr.blr = NULL;
- inBlr.blrLength = 0;
- inBlr.bufferLength = 0;
+ RoutineMessage inMsg(*attachment->att_pool);
+ RoutineMessage outMsg(*attachment->att_pool);
- BlrMessage outBlr;
- outBlr.blr = NULL;
- outBlr.blrLength = 0;
- outBlr.bufferLength = 0;
-
if (!X.RDB$ENGINE_NAME.NULL || !X.RDB$FUNCTION_BLR.NULL)
{
if (!X.RDB$ENGINE_NAME.NULL)
@@ -403,7 +396,7 @@
function->fun_external =
dbb->dbb_extManager.makeFunction(tdbb, function, X.RDB$ENGINE_NAME,
(X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin(),
- &inBlr, &outBlr);
+ &inMsg, &outMsg);
if (!function->fun_external)
function->setDefined(false);
@@ -422,7 +415,7 @@
try
{
MET_parse_routine_blr(tdbb, function, &X.RDB$FUNCTION_BLR, csb,
- !X.RDB$ENGINE_NAME.NULL, inBlr, outBlr);
+ !X.RDB$ENGINE_NAME.NULL, inMsg, outMsg);
}
catch (const Exception&)
{
Modified: firebird/trunk/src/jrd/dfw.epp
===================================================================
--- firebird/trunk/src/jrd/dfw.epp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/jrd/dfw.epp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -5651,7 +5651,7 @@
try
{
- BlrMessage dummy;
+ RoutineMessage dummy(*csb_pool);
MET_parse_routine_blr(tdbb, function, &FUN.RDB$FUNCTION_BLR, csb, false,
dummy, dummy);
Modified: firebird/trunk/src/jrd/jrd.cpp
===================================================================
--- firebird/trunk/src/jrd/jrd.cpp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/jrd/jrd.cpp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -642,10 +642,9 @@
return;
extTrigger = dbb->dbb_extManager.makeTrigger(tdbb, this, engine, entryPoint, extBody.c_str(),
- (relation ? (type & 1 ?
- Firebird::ExternalTrigger::TYPE_BEFORE :
- Firebird::ExternalTrigger::TYPE_AFTER) :
- Firebird::ExternalTrigger::TYPE_DATABASE));
+ (relation ?
+ (type & 1 ? ExternalTrigger::TYPE_BEFORE : ExternalTrigger::TYPE_AFTER) :
+ Firebird::ExternalTrigger::TYPE_DATABASE));
}
void Trigger::release(thread_db* tdbb)
Modified: firebird/trunk/src/jrd/met.epp
===================================================================
--- firebird/trunk/src/jrd/met.epp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/jrd/met.epp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -2975,16 +2975,9 @@
}
END_FOR
- BlrMessage inBlr;
- inBlr.blr = NULL;
- inBlr.blrLength = 0;
- inBlr.bufferLength = 0;
+ RoutineMessage inMsg(*tdbb->getDefaultPool());
+ RoutineMessage outMsg(*tdbb->getDefaultPool());
- BlrMessage outBlr;
- outBlr.blr = NULL;
- outBlr.blrLength = 0;
- outBlr.bufferLength = 0;
-
const bool external = !P.RDB$ENGINE_NAME.NULL; // ODS_12_0
if (external)
@@ -3004,7 +2997,7 @@
procedure->setExternal(dbb->dbb_extManager.makeProcedure(
tdbb, procedure, P.RDB$ENGINE_NAME,
- (P.RDB$ENTRYPOINT.NULL ? "" : P.RDB$ENTRYPOINT), body.begin(), &inBlr, &outBlr));
+ (P.RDB$ENTRYPOINT.NULL ? "" : P.RDB$ENTRYPOINT), body.begin(), &inMsg, &outMsg));
}
Array<NestConst<Parameter> >& paramArray = procedure->getOutputFields();
@@ -3055,7 +3048,7 @@
{
MET_parse_routine_blr(tdbb, procedure,
(P.RDB$PROCEDURE_BLR.NULL ? NULL : &P.RDB$PROCEDURE_BLR), csb, external,
- inBlr, outBlr);
+ inMsg, outMsg);
}
catch (const Exception&)
{
@@ -4304,7 +4297,7 @@
// Generate BLR message for external procedures
static bool gen_ext_message(thread_db* tdbb, CompilerScratch* csb, UCharBuffer& blr, UCHAR message,
- UCHAR message2, const Array<NestConst<Parameter> >& parameters, const BlrMessage& extBlr,
+ UCHAR message2, const Array<NestConst<Parameter> >& parameters, const RoutineMessage& extMsg,
UCharBuffer& appendBlr)
{
const size_t prevAppendBlrSize = appendBlr.getCount();
@@ -4315,9 +4308,9 @@
dsc shortDesc;
shortDesc.makeShort(0);
- if (extBlr.blr)
+ if (extMsg.blr.hasData())
{
- BlrReader reader(extBlr.blr, extBlr.blrLength);
+ BlrReader reader(extMsg.blr.begin(), extMsg.blr.getCount());
reader.checkByte(blr_version5);
reader.checkByte(blr_begin);
@@ -4372,11 +4365,11 @@
reader.checkByte(blr_end);
reader.checkByte(blr_eoc);
- if (offset != extBlr.bufferLength)
+ if (offset != extMsg.bufferLength)
{
status_exception::raise(
Arg::Gds(isc_ee_blr_mismatch_length) <<
- Arg::Num(extBlr.bufferLength) <<
+ Arg::Num(extMsg.bufferLength) <<
Arg::Num(offset));
}
}
@@ -4458,8 +4451,8 @@
// Parse routine BLR.
-void MET_parse_routine_blr(thread_db* tdbb, Routine* routine, bid* blob_id,
- CompilerScratch* csb, bool external, const BlrMessage& extInBlr, const BlrMessage& extOutBlr)
+void MET_parse_routine_blr(thread_db* tdbb, Routine* routine, bid* blob_id, CompilerScratch* csb,
+ bool external, const RoutineMessage& extInMsg, const RoutineMessage& extOutMsg)
{
SET_TDBB(tdbb);
Jrd::Attachment* attachment = tdbb->getAttachment();
@@ -4477,9 +4470,9 @@
UCharBuffer appendBlr;
bool genExtIn = gen_ext_message(tdbb, csb, tmp, e_extrout_input_message,
- e_extrout_input_message2, routine->getInputFields(), extInBlr, appendBlr);
+ e_extrout_input_message2, routine->getInputFields(), extInMsg, appendBlr);
bool genExtOut = gen_ext_message(tdbb, csb, tmp, e_extrout_output_message,
- e_extrout_output_message2, routine->getOutputFields(), extOutBlr, appendBlr);
+ e_extrout_output_message2, routine->getOutputFields(), extOutMsg, appendBlr);
dsc shortDesc;
shortDesc.makeShort(0);
Modified: firebird/trunk/src/jrd/met_proto.h
===================================================================
--- firebird/trunk/src/jrd/met_proto.h 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/jrd/met_proto.h 2013-01-29 01:21:32 UTC (rev 57629)
@@ -104,8 +104,8 @@
Jrd::DmlNode* MET_parse_blob(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::bid*, Jrd::CompilerScratch**,
Jrd::JrdStatement**, bool, bool);
void MET_parse_routine_blr(Jrd::thread_db*, Jrd::Routine*, Jrd::bid*, Jrd::CompilerScratch*,
- bool, const Firebird::BlrMessage& extInBlr,
- const Firebird::BlrMessage& extOutBlr);
+ bool, const Jrd::RoutineMessage& extInMsg,
+ const Jrd::RoutineMessage& extOutMsg);
void MET_parse_sys_trigger(Jrd::thread_db*, Jrd::jrd_rel*);
void MET_post_existence(Jrd::thread_db*, Jrd::jrd_rel*);
void MET_prepare(Jrd::thread_db*, Jrd::jrd_tra*, USHORT, const UCHAR*);
Modified: firebird/trunk/src/msgs/facilities2.sql
===================================================================
--- firebird/trunk/src/msgs/facilities2.sql 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/msgs/facilities2.sql 2013-01-29 01:21:32 UTC (rev 57629)
@@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
--
-('2012-09-20 12:25:00', 'JRD', 0, 727)
+('2013-01-27 13:00:00', 'JRD', 0, 729)
('2012-01-23 20:10:30', 'QLI', 1, 532)
('2009-07-16 05:26:11', 'GFIX', 3, 121)
('1996-11-07 13:39:40', 'GPRE', 4, 1)
Modified: firebird/trunk/src/msgs/messages2.sql
===================================================================
--- firebird/trunk/src/msgs/messages2.sql 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/msgs/messages2.sql 2013-01-29 01:21:32 UTC (rev 57629)
@@ -834,6 +834,8 @@
('no_providers', NULL, 'why.cpp', NULL, 0, 724, NULL, 'No providers loaded', NULL, NULL);
('null_spb', NULL, 'why.cpp', NULL, 0, 725, NULL, 'NULL data with non-zero SPB length', NULL, NULL);
('max_args_exceeded', NULL, 'ExprNodes.cpp', NULL, 0, 726, NULL, 'Maximum (@1) number of arguments exceeded for function @2', NULL, NULL)
+('ee_blr_mismatch_names_count', NULL, 'ExtEngineManager.cpp', NULL, 0, 727, NULL, 'External BLR message mismatch: names count = @1, blr count = @2', NULL, NULL)
+('ee_blr_mismatch_name_not_found', NULL, 'ExtEngineManager.cpp', NULL, 0, 728, NULL, 'External BLR message mismatch: name @1 not found', NULL, NULL)
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
Modified: firebird/trunk/src/msgs/system_errors2.sql
===================================================================
--- firebird/trunk/src/msgs/system_errors2.sql 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/msgs/system_errors2.sql 2013-01-29 01:21:32 UTC (rev 57629)
@@ -733,6 +733,8 @@
(-902, '39', '000', 0, 724, 'no_providers', NULL, NULL)
(-104, '42', '818', 0, 725, 'null_spb', NULL, NULL)
(-833, '42', '000', 0, 726, 'max_args_exceeded', NULL, NULL)
+(-901, '42', '000', 0, 727, 'ee_blr_mismatch_names_count', NULL, NULL)
+(-901, '42', '000', 0, 728, 'ee_blr_mismatch_name_not_found', NULL, NULL)
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
Modified: firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp
===================================================================
--- firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp 2013-01-26 08:38:50 UTC (rev 57628)
+++ firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp 2013-01-29 01:21:32 UTC (rev 57629)
@@ -153,11 +153,11 @@
virtual void FB_CALL openAttachment(Error* error, ExternalContext* context);
virtual void FB_CALL closeAttachment(Error* error, ExternalContext* context);
virtual ExternalFunction* FB_CALL makeFunction(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata, BlrMessage* inBlr, BlrMessage* outBlr);
+ const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg);
virtual ExternalProcedure* FB_CALL makeProcedure(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata, BlrMessage* inBlr, BlrMessage* outBlr);
+ const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg);
virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata);
+ const IRoutineMetadata* metadata, ITriggerMessage* fieldsMsg);
public:
virtual void FB_CALL dispose(Error* error);
@@ -207,7 +207,7 @@
{
public:
SharedFunction(Error* error, Engine* aEngine, ExternalContext* context,
- const IRoutineMetadata* aMetadata, BlrMessage* inBlr, BlrMessage* outBlr)
+ const IRoutineMetadata* aMetadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg)
: engine(aEngine),
metadata(aMetadata),
moduleName(*getDefaultMemoryPool()),
@@ -217,7 +217,7 @@
{
engine->loadModule(metadata, &moduleName, &entryPoint);
FunctionNode* node = engine->findNode<FunctionNode>(registeredFunctions, moduleName, entryPoint);
- node->factory->setup(error, context, metadata, inBlr, outBlr);
+ node->factory->setup(error, context, metadata, inMsg, outMsg);
}
virtual ~SharedFunction()
@@ -275,7 +275,7 @@
{
public:
SharedProcedure(Error* error, Engine* aEngine, ExternalContext* context,
- const IRoutineMetadata* aMetadata, BlrMessage* inBlr, BlrMessage* outBlr)
+ const IRoutineMetadata* aMetadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg)
: engine(aEngine),
metadata(aMetadata),
moduleName(*getDefaultMemoryPool()),
@@ -285,7 +285,7 @@
{
engine->loadModule(metadata, &moduleName, &entryPoint);
ProcedureNode* node = engine->findNode<ProcedureNode>(registeredProcedures, moduleName, entryPoint);
- node->factory->setup(error, context, metadata, inBlr, outBlr);
+ node->factory->setup(error, context, metadata, inMsg, outMsg);
}
virtual ~SharedProcedure()
@@ -351,7 +351,7 @@
{
public:
SharedTrigger(Error* error, Engine* aEngine, ExternalContext* context,
- const IRoutineMetadata* aMetadata)
+ const IRoutineMetadata* aMetadata, ITriggerMessage* fieldsMsg)
: engine(aEngine),
metadata(aMetadata),
moduleName(*getDefaultMemoryPool()),
@@ -361,7 +361,7 @@
{
engine->loadModule(metadata, &moduleName, &entryPoint);
TriggerNode* node = engine->findNode<TriggerNode>(registeredTriggers, moduleName, entryPoint);
- node->factory->setup(error, context, metadata);
+ node->factory->setup(error, context, metadata, fieldsMsg);
}
virtual ~SharedTrigger()
@@ -681,11 +681,11 @@
ExternalFunction* FB_CALL Engine::makeFunction(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata, BlrMessage* inBlr, BlrMessage* outBlr)
+ const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg)
{
try
{
- return new SharedFunction(error, this, context, metadata, inBlr, outBlr);
+ return new SharedFunction(error, this, context, metadata, inMsg, outMsg);
}
catch (const ThrowError::Exception& e)
{
@@ -696,11 +696,11 @@
ExternalProcedure* FB_CALL Engine::makeProcedure(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata, BlrMessage* inBlr, BlrMessage* outBlr)
+ const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg)
{
try
{
- return new SharedProcedure(error, this, context, metadata, inBlr, outBlr);
+ return new SharedProcedure(error, this, context, metadata, inMsg, outMsg);
}
catch (const ThrowError::Exception& e)
{
@@ -711,11 +711,11 @@
ExternalTrigger* FB_CALL Engine::makeTrigger(Error* error, ExternalContext* context,
- const IRoutineMetadata* metadata)
+ const IRoutineMetadata* metadata, ITriggerMessage* fieldsMsg)
{
try
{
- return new SharedTrigger(error, this, context, metadata);
+ return new SharedTrigger(error, this, context, metadata, fieldsMsg);
}
catch (const ThrowError::Exception& e)
{
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|