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. |