diff --git a/examples/udr/UdrCppExample.cpp b/examples/udr/UdrCppExample.cpp index f6616c7ca6..f7dc60b1af 100644 --- a/examples/udr/UdrCppExample.cpp +++ b/examples/udr/UdrCppExample.cpp @@ -30,6 +30,8 @@ using namespace Firebird; using namespace Firebird::Udr; +typedef IMaster* (ISC_EXPORT *FuncGetMasterInterface)(); + typedef ISC_LONG (ISC_EXPORT_VARARG *FuncEventBlock)(ISC_UCHAR**, ISC_UCHAR**, ISC_USHORT, ...); typedef ISC_STATUS (ISC_EXPORT *FuncWaitForEvent)(ISC_STATUS*, isc_db_handle*, short, const ISC_UCHAR*, ISC_UCHAR*); @@ -50,6 +52,87 @@ typedef ISC_STATUS (ISC_EXPORT *FuncDsqlPrepare)(ISC_STATUS*, isc_tr_handle*, is unsigned short, const ISC_SCHAR*, unsigned short, XSQLDA*); +namespace +{ + template + class AutoDispose + { + public: + AutoDispose(T* aPtr = NULL) + : ptr(aPtr) + { + } + + ~AutoDispose() + { + clear(); + } + + AutoDispose& operator =(T* aPtr) + { + clear(); + ptr = aPtr; + return *this; + } + + operator T*() + { + return ptr; + } + + operator const T*() const + { + return ptr; + } + + bool operator !() const + { + return !ptr; + } + + bool hasData() const + { + return ptr != NULL; + } + + T* operator ->() + { + return ptr; + } + + T* release() + { + T* tmp = ptr; + ptr = NULL; + return tmp; + } + + void reset(T* aPtr = NULL) + { + if (aPtr != ptr) + { + clear(); + ptr = aPtr; + } + } + + private: + void clear() + { + if (ptr) + ptr->dispose(); + } + + // not implemented + AutoDispose(AutoDispose&); + void operator =(AutoDispose&); + + private: + T* ptr; + }; +} + + /*** create function wait_event ( event_name varchar(31) character set ascii @@ -135,6 +218,7 @@ private: isc_stmt_handle stmtHandle; // ISC entry points + FuncGetMasterInterface funcGetMasterInterface; FuncDsqlAllocateStatement funcDsqlAllocateStatement; FuncDsqlDescribe funcDsqlDescribe; FuncDsqlDescribeBind funcDsqlDescribeBind; @@ -246,6 +330,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val return; // ISC entry points + funcGetMasterInterface = (FuncGetMasterInterface) getEntryPoint(context, "fb_get_master_interface"); funcDsqlAllocateStatement = (FuncDsqlAllocateStatement) getEntryPoint(context, "isc_dsql_allocate_statement"); funcDsqlDescribe = (FuncDsqlDescribe) getEntryPoint(context, "isc_dsql_describe"); @@ -265,14 +350,33 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val "select data_source from replicate_config where name = ?", SQL_DIALECT_CURRENT, NULL), statusVector); + AutoDispose master(funcGetMasterInterface()); + AutoDispose status(master->getStatus()); + + const char* table = metadata->getTriggerTable(status); + ThrowError::check(status->get()); + + // Skip the first exclamation point, separing 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). + if (info) + info = strchr(info + 1, '!'); + + if (info) + ++info; + else + info = ""; + inSqlDa = reinterpret_cast(new char[(XSQLDA_LENGTH(1))]); inSqlDa->version = SQLDA_VERSION1; inSqlDa->sqln = 1; ThrowError::check(funcDsqlDescribeBind(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), metaInfo->info, inSqlDa->sqlvar[0].sqllen); - *reinterpret_cast(inSqlDa->sqlvar[0].sqldata) = strlen(metaInfo->info); + strncpy(inSqlDa->sqlvar[0].sqldata + sizeof(short), info, inSqlDa->sqlvar[0].sqllen); + *reinterpret_cast(inSqlDa->sqlvar[0].sqldata) = strlen(info); XSQLDA* outSqlDa = reinterpret_cast(new char[(XSQLDA_LENGTH(1))]); outSqlDa->version = SQLDA_VERSION1; @@ -304,7 +408,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val const char* name = val->getName(ThrowError()); strcat(buffer, " p"); - sprintf(buffer + strlen(buffer), "%d type of column \"%s\".\"%s\" = ?", i, metaInfo->table, name); + sprintf(buffer + strlen(buffer), "%d type of column \"%s\".\"%s\" = ?", i, table, name); } strcat(buffer, @@ -313,7 +417,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val "begin\n" " execute statement ('insert into \""); - strcat(buffer, metaInfo->table); + strcat(buffer, table); strcat(buffer, "\" ("); for (int i = 1; i <= count; ++i) @@ -449,7 +553,7 @@ FB_UDR_BEGIN_TRIGGER(replicate) { case SQL_VARYING: { - uint len; + unsigned len; const char* s = val->getString(ThrowError(), &len); *reinterpret_cast(var->sqldata) = len; memcpy(var->sqldata + sizeof(unsigned short), s, len); diff --git a/src/include/FirebirdExternalApi.h b/src/include/FirebirdExternalApi.h index 58d6d541f1..a9fc3472d3 100644 --- a/src/include/FirebirdExternalApi.h +++ b/src/include/FirebirdExternalApi.h @@ -152,6 +152,19 @@ public: }; +class IRoutineMetadata // : public IVersioned +{ +public: + virtual const char* FB_CARG getPackage(IStatus* status) const = 0; + virtual const char* FB_CARG getName(IStatus* status) const = 0; + virtual const char* FB_CARG getEntryPoint(IStatus* status) const = 0; + virtual const char* FB_CARG getBody(IStatus* status) const = 0; + virtual const char* FB_CARG getTriggerTable(IStatus* status) const = 0; + virtual ExternalTrigger::Type FB_CARG getTriggerType(IStatus* status) const = 0; +}; +// #define FB_I_ROUTINE_METADATA_VERSION (FB_VERSIONED_VERSION + 6) + + // In SuperServer, shared by all attachments to one database and disposed when last (non-external) // user attachment to the database is closed. class ExternalEngine : public IPluginBase @@ -175,12 +188,11 @@ public: // 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 char* package, const char* name, const char* entryPoint, const char* body) = 0; + const IRoutineMetadata* metadata) = 0; virtual ExternalProcedure* FB_CALL makeProcedure(Error* error, ExternalContext* context, - const char* package, const char* name, const char* entryPoint, const char* body) = 0; + const IRoutineMetadata* metadata) = 0; virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context, - const char* name, const char* entryPoint, const char* body, - const char* table, ExternalTrigger::Type type) = 0; + const IRoutineMetadata* metadata) = 0; }; #define FB_EXTERNAL_ENGINE_VERSION (FB_PLUGIN_VERSION + 7) diff --git a/src/include/FirebirdUdr.h b/src/include/FirebirdUdr.h index ed61cd208c..639e16da26 100644 --- a/src/include/FirebirdUdr.h +++ b/src/include/FirebirdUdr.h @@ -34,24 +34,6 @@ namespace Firebird //------------------------------------------------------------------------------ -// Metadata information passed from the UDR engine to user's routines factories when asking to -// create routines instances. -struct MetaInfo -{ - const char* package; // package name - NULL from triggers - const char* name; // metadata object name - const char* entryPoint; // external routine's name - const char* info; // misc. info encoded on the external name - const char* body; // body text -}; - -struct TriggerMetaInfo : public MetaInfo -{ - ExternalTrigger::Type type; // trigger type - const char* table; // table name -}; - - // Factory classes. They should be singletons instances created by user's modules and // registered. When UDR engine is going to load a routine, it calls newItem. @@ -59,21 +41,21 @@ class FunctionFactory { public: virtual const char* FB_CALL getName() = 0; - virtual ExternalFunction* FB_CALL newItem(MetaInfo* metaInfo) = 0; + virtual ExternalFunction* FB_CALL newItem(const IRoutineMetadata* metadata) = 0; }; class ProcedureFactory { public: virtual const char* FB_CALL getName() = 0; - virtual ExternalProcedure* FB_CALL newItem(MetaInfo* metaInfo) = 0; + virtual ExternalProcedure* FB_CALL newItem(const IRoutineMetadata* metadata) = 0; }; class TriggerFactory { public: virtual const char* FB_CALL getName() = 0; - virtual ExternalTrigger* FB_CALL newItem(TriggerMetaInfo* metaInfo) = 0; + virtual ExternalTrigger* FB_CALL newItem(const IRoutineMetadata* metadata) = 0; }; diff --git a/src/include/FirebirdUdrCpp.h b/src/include/FirebirdUdrCpp.h index d00eda5106..5c97c58f3d 100644 --- a/src/include/FirebirdUdrCpp.h +++ b/src/include/FirebirdUdrCpp.h @@ -503,7 +503,7 @@ public: } public: - MetaInfo* metaInfo; + const IRoutineMetadata* metadata; }; @@ -525,7 +525,7 @@ public: } public: - MetaInfo* metaInfo; + const IRoutineMetadata* metadata; }; @@ -547,7 +547,7 @@ public: } public: - TriggerMetaInfo* metaInfo; + const IRoutineMetadata* metadata; }; @@ -566,10 +566,10 @@ public: return name; } - virtual ExternalFunction* FB_CALL newItem(MetaInfo* metaInfo) + virtual ExternalFunction* FB_CALL newItem(const IRoutineMetadata* metadata) { Function* function = new T(); - function->metaInfo = metaInfo; + function->metadata = metadata; return function; } @@ -593,10 +593,10 @@ public: return name; } - virtual ExternalProcedure* FB_CALL newItem(MetaInfo* metaInfo) + virtual ExternalProcedure* FB_CALL newItem(const IRoutineMetadata* metadata) { Procedure* procedure = new T(); - procedure->metaInfo = metaInfo; + procedure->metadata = metadata; return procedure; } @@ -620,10 +620,10 @@ public: return name; } - virtual ExternalTrigger* FB_CALL newItem(TriggerMetaInfo* metaInfo) + virtual ExternalTrigger* FB_CALL newItem(const IRoutineMetadata* metadata) { Trigger* trigger = new T(); - trigger->metaInfo = metaInfo; + trigger->metadata = metadata; return trigger; } diff --git a/src/jrd/ExtEngineManager.cpp b/src/jrd/ExtEngineManager.cpp index b2cbcadbd5..8b59fab9ba 100644 --- a/src/jrd/ExtEngineManager.cpp +++ b/src/jrd/ExtEngineManager.cpp @@ -286,10 +286,11 @@ void* FB_CALL ExtEngineManager::ExternalContextImpl::setInfo(int code, void* val ExtEngineManager::Function::Function(thread_db* tdbb, ExtEngineManager* aExtManager, - ExternalEngine* aEngine, ExternalFunction* aFunction, + ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalFunction* aFunction, const Jrd::Function* aUdf) : extManager(aExtManager), engine(aEngine), + metadata(aMetadata), function(aFunction), udf(aUdf), database(tdbb->getDatabase()) @@ -384,10 +385,11 @@ void ExtEngineManager::Function::execute(thread_db* tdbb, const NestValueArray& ExtEngineManager::Procedure::Procedure(thread_db* tdbb, ExtEngineManager* aExtManager, - ExternalEngine* aEngine, ExternalProcedure* aProcedure, + ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalProcedure* aProcedure, const jrd_prc* aPrc) : extManager(aExtManager), engine(aEngine), + metadata(aMetadata), procedure(aProcedure), prc(aPrc), database(tdbb->getDatabase()) @@ -467,10 +469,11 @@ bool ExtEngineManager::ResultSet::fetch(thread_db* tdbb) ExtEngineManager::Trigger::Trigger(thread_db* tdbb, ExtEngineManager* aExtManager, - ExternalEngine* aEngine, ExternalTrigger* aTrigger, + ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalTrigger* aTrigger, const Jrd::Trigger* aTrg) : extManager(aExtManager), engine(aEngine), + metadata(aMetadata), trigger(aTrigger), trg(aTrg), database(tdbb->getDatabase()) @@ -651,14 +654,19 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons CallerName(obj_udf, udf->getName().identifier) : CallerName(obj_package_header, udf->getName().package))); + MemoryPool& pool = *tdbb->getDefaultPool(); + AutoPtr metadata(FB_NEW(pool) RoutineMetadata(pool)); + metadata->package = udf->getName().package; + metadata->name = udf->getName().identifier; + metadata->entryPoint = entryPointTrimmed; + metadata->body = body; + ExternalFunction* externalFunction; { // scope Attachment::Checkout attCout(tdbb->getAttachment()); - externalFunction = attInfo->engine->makeFunction(RaiseError(), - attInfo->context, udf->getName().package.nullStr(), udf->getName().identifier.c_str(), - entryPointTrimmed.nullStr(), body.nullStr()); + externalFunction = attInfo->engine->makeFunction(RaiseError(), attInfo->context, metadata); if (!externalFunction) { @@ -670,7 +678,8 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons try { - return FB_NEW(getPool()) Function(tdbb, this, attInfo->engine, externalFunction, udf); + return FB_NEW(getPool()) Function(tdbb, this, attInfo->engine, metadata.release(), + externalFunction, udf); } catch (...) { @@ -693,14 +702,19 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co CallerName(obj_procedure, prc->getName().identifier) : CallerName(obj_package_header, prc->getName().package))); + MemoryPool& pool = *tdbb->getDefaultPool(); + AutoPtr metadata(FB_NEW(pool) RoutineMetadata(pool)); + metadata->package = prc->getName().package; + metadata->name = prc->getName().identifier; + metadata->entryPoint = entryPointTrimmed; + metadata->body = body; + ExternalProcedure* externalProcedure; { // scope Attachment::Checkout attCout(tdbb->getAttachment()); - externalProcedure = attInfo->engine->makeProcedure(RaiseError(), - attInfo->context, prc->getName().package.nullStr(), prc->getName().identifier.c_str(), - entryPointTrimmed.nullStr(), body.nullStr()); + externalProcedure = attInfo->engine->makeProcedure(RaiseError(), attInfo->context, metadata); if (!externalProcedure) { @@ -712,7 +726,8 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co try { - return FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine, externalProcedure, prc); + return FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine, metadata.release(), + externalProcedure, prc); } catch (...) { @@ -729,22 +744,25 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const string entryPointTrimmed = entryPoint; entryPointTrimmed.trim(); - MetaName relationNameTrimmed; - if (trg->relation) - relationNameTrimmed = trg->relation->rel_name; - EngineAttachmentInfo* attInfo = getEngineAttachment(tdbb, engine); ContextManager ctxManager(tdbb, attInfo, attInfo->adminCharSet, CallerName(obj_trigger, trg->name)); + MemoryPool& pool = *tdbb->getDefaultPool(); + AutoPtr metadata(FB_NEW(pool) RoutineMetadata(pool)); + metadata->name = trg->name; + metadata->entryPoint = entryPointTrimmed; + metadata->body = body; + metadata->triggerType = type; + if (trg->relation) + metadata->triggerTable = trg->relation->rel_name; + ExternalTrigger* externalTrigger; { // scope Attachment::Checkout attCout(tdbb->getAttachment()); - externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context, - trg->name.c_str(), entryPointTrimmed.nullStr(), body.nullStr(), - relationNameTrimmed.c_str(), type); + externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context, metadata); if (!externalTrigger) { @@ -755,7 +773,8 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const try { - return FB_NEW(getPool()) Trigger(tdbb, this, attInfo->engine, externalTrigger, trg); + return FB_NEW(getPool()) Trigger(tdbb, this, attInfo->engine, metadata.release(), + externalTrigger, trg); } catch (...) { diff --git a/src/jrd/ExtEngineManager.h b/src/jrd/ExtEngineManager.h index 91b52e8aa0..32f9ffddb1 100644 --- a/src/jrd/ExtEngineManager.h +++ b/src/jrd/ExtEngineManager.h @@ -61,6 +61,59 @@ private: template class ContextManager; class TransactionImpl; + class RoutineMetadata : public Firebird::IRoutineMetadata, public Firebird::PermanentStorage + { + public: + RoutineMetadata(MemoryPool& pool) + : PermanentStorage(pool), + package(pool), + name(pool), + entryPoint(pool), + body(pool), + triggerTable(pool), + triggerType(Firebird::ExternalTrigger::Type(0)) + { + } + + virtual const char* FB_CARG getPackage(Firebird::IStatus* /*status*/) const + { + return package.nullStr(); + } + + virtual const char* FB_CARG getName(Firebird::IStatus* /*status*/) const + { + return name.c_str(); + } + + virtual const char* FB_CARG getEntryPoint(Firebird::IStatus* /*status*/) const + { + return entryPoint.c_str(); + } + + virtual const char* FB_CARG getBody(Firebird::IStatus* /*status*/) const + { + return body.c_str(); + } + + virtual const char* FB_CARG getTriggerTable(Firebird::IStatus* /*status*/) const + { + return triggerTable.c_str(); + } + + virtual Firebird::ExternalTrigger::Type FB_CARG getTriggerType(Firebird::IStatus* /*status*/) const + { + return triggerType; + } + + public: + Firebird::MetaName package; + Firebird::MetaName name; + Firebird::string entryPoint; + Firebird::string body; + Firebird::MetaName triggerTable; + Firebird::ExternalTrigger::Type triggerType; + }; + class ExternalContextImpl : public Firebird::ExternalContext { friend class AttachmentImpl; @@ -130,6 +183,7 @@ public: public: Function(thread_db* tdbb, ExtEngineManager* aExtManager, Firebird::ExternalEngine* aEngine, + RoutineMetadata* aMetadata, Firebird::ExternalFunction* aFunction, const Jrd::Function* aUdf); ~Function(); @@ -140,6 +194,7 @@ public: private: ExtEngineManager* extManager; Firebird::ExternalEngine* engine; + Firebird::AutoPtr metadata; Firebird::ExternalFunction* function; const Jrd::Function* udf; Database* database; @@ -152,6 +207,7 @@ public: public: Procedure(thread_db* tdbb, ExtEngineManager* aExtManager, Firebird::ExternalEngine* aEngine, + RoutineMetadata* aMetadata, Firebird::ExternalProcedure* aProcedure, const jrd_prc* aPrc); ~Procedure(); @@ -161,6 +217,7 @@ public: private: ExtEngineManager* extManager; Firebird::ExternalEngine* engine; + Firebird::AutoPtr metadata; Firebird::ExternalProcedure* procedure; const jrd_prc* prc; Database* database; @@ -191,6 +248,7 @@ public: public: Trigger(thread_db* tdbb, ExtEngineManager* aExtManager, Firebird::ExternalEngine* aEngine, + RoutineMetadata* aMetadata, Firebird::ExternalTrigger* aTrigger, const Jrd::Trigger* aTrg); ~Trigger(); @@ -205,6 +263,7 @@ public: ExtEngineManager* extManager; Firebird::ExternalEngine* engine; + Firebird::AutoPtr metadata; Firebird::ExternalTrigger* trigger; const Jrd::Trigger* trg; Database* database; diff --git a/src/plugins/udr_engine/UdrEngine.cpp b/src/plugins/udr_engine/UdrEngine.cpp index 3579246614..cbf56f6cd1 100644 --- a/src/plugins/udr_engine/UdrEngine.cpp +++ b/src/plugins/udr_engine/UdrEngine.cpp @@ -36,6 +36,7 @@ #include "../common/os/mod_loader.h" #include "../common/os/path_utils.h" #include "../common/classes/ImplementHelper.h" +#include "../common/StatusHolder.h" namespace Firebird @@ -130,7 +131,7 @@ public: } public: - void loadModule(const string& str, PathName* moduleName, string* entryPoint, string* info); + void loadModule(const IRoutineMetadata* metadata, PathName* moduleName, string* entryPoint); template ObjType* getChild( GenericMap > >& children, SharedObjType* sharedObj, ExternalContext* context, NodeType* nodes, SortedArray& sharedObjs, @@ -138,12 +139,12 @@ public: template void deleteChildren( GenericMap > >& children); - template T* findNode(T* nodes, const PathName& moduleName, - T2* metaInfo); + template T* findNode(T* nodes, const PathName& moduleName, + const string& entryPoint); private: - template T2* getNode(T* nodes, const PathName& moduleName, - T3* metaInfo); + template T2* getNode(T* nodes, const PathName& moduleName, + const IRoutineMetadata* metadata, const string& entryPoint); public: virtual int FB_CALL getVersion(Error* error); @@ -151,12 +152,11 @@ public: 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 char* package, const char* name, const char* entryPoint, const char* body); + const IRoutineMetadata* metadata); virtual ExternalProcedure* FB_CALL makeProcedure(Error* error, ExternalContext* context, - const char* package, const char* name, const char* entryPoint, const char* body); + const IRoutineMetadata* metadata); virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context, - const char* name, const char* entryPoint, const char* body, const char* table, - ExternalTrigger::Type type); + const IRoutineMetadata* metadata); public: virtual void FB_CALL dispose(Error* error); @@ -205,25 +205,16 @@ static TriggerNode* registeredTriggers = NULL; class SharedFunction : public ExternalFunction { public: - SharedFunction(Engine* aEngine, const string& aPackage, const string& aName, - const string& aEntryPoint, const string& aBody) + SharedFunction(Engine* aEngine, const IRoutineMetadata* aMetadata) : engine(aEngine), - package(*getDefaultMemoryPool(), aPackage), - name(*getDefaultMemoryPool(), aName), - entryPoint(*getDefaultMemoryPool()), - body(*getDefaultMemoryPool(), aBody), + metadata(aMetadata), moduleName(*getDefaultMemoryPool()), + entryPoint(*getDefaultMemoryPool()), info(*getDefaultMemoryPool()), children(*getDefaultMemoryPool()) { - engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info); - metaInfo.package = package.nullStr(); - metaInfo.name = name.c_str(); - metaInfo.entryPoint = entryPoint.c_str(); - metaInfo.body = body.c_str(); - metaInfo.info = info.c_str(); - - engine->findNode(registeredFunctions, moduleName, &metaInfo); + engine->loadModule(metadata, &moduleName, &entryPoint); + engine->findNode(registeredFunctions, moduleName, entryPoint); } virtual ~SharedFunction() @@ -266,13 +257,10 @@ public: } public: - MetaInfo metaInfo; Engine* engine; - string package; - string name; - string entryPoint; - string body; + const IRoutineMetadata* metadata; PathName moduleName; + string entryPoint; string info; GenericMap > > children; }; @@ -284,25 +272,15 @@ public: class SharedProcedure : public ExternalProcedure { public: - SharedProcedure(Engine* aEngine, const string& aPackage, const string& aName, - const string& aEntryPoint, const string& aBody) + SharedProcedure(Engine* aEngine, const IRoutineMetadata* aMetadata) : engine(aEngine), - package(*getDefaultMemoryPool(), aPackage), - name(*getDefaultMemoryPool(), aName), - entryPoint(*getDefaultMemoryPool(), aEntryPoint), - body(*getDefaultMemoryPool(), aBody), moduleName(*getDefaultMemoryPool()), + entryPoint(*getDefaultMemoryPool()), info(*getDefaultMemoryPool()), children(*getDefaultMemoryPool()) { - engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info); - metaInfo.package = package.nullStr(); - metaInfo.name = name.c_str(); - metaInfo.entryPoint = entryPoint.c_str(); - metaInfo.body = body.c_str(); - metaInfo.info = info.c_str(); - - engine->findNode(registeredProcedures, moduleName, &metaInfo); + engine->loadModule(metadata, &moduleName, &entryPoint); + engine->findNode(registeredProcedures, moduleName, entryPoint); } virtual ~SharedProcedure() @@ -352,13 +330,10 @@ public: } public: - MetaInfo metaInfo; Engine* engine; - string package; - string name; - string entryPoint; - string body; + const IRoutineMetadata* metadata; PathName moduleName; + string entryPoint; string info; GenericMap > > children; }; @@ -370,28 +345,16 @@ public: class SharedTrigger : public ExternalTrigger { public: - SharedTrigger(Engine* aEngine, const string& aName, const string& aEntryPoint, - const string& aBody, const string& aTable, ExternalTrigger::Type aType) + SharedTrigger(Engine* aEngine, const IRoutineMetadata* aMetadata) : engine(aEngine), - name(*getDefaultMemoryPool(), aName), - entryPoint(*getDefaultMemoryPool(), aEntryPoint), - body(*getDefaultMemoryPool(), aBody), + metadata(aMetadata), moduleName(*getDefaultMemoryPool()), + entryPoint(*getDefaultMemoryPool()), info(*getDefaultMemoryPool()), - table(*getDefaultMemoryPool(), aTable), - type(aType), children(*getDefaultMemoryPool()) { - engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info); - metaInfo.package = NULL; - metaInfo.name = name.c_str(); - metaInfo.entryPoint = entryPoint.c_str(); - metaInfo.body = body.c_str(); - metaInfo.info = info.c_str(); - metaInfo.type = type; - metaInfo.table = table.nullStr(); - - engine->findNode(registeredTriggers, moduleName, &metaInfo); + engine->loadModule(metadata, &moduleName, &entryPoint); + engine->findNode(registeredTriggers, moduleName, entryPoint); } virtual ~SharedTrigger() @@ -434,15 +397,11 @@ public: } public: - TriggerMetaInfo metaInfo; Engine* engine; - string name; - string entryPoint; - string body; + const IRoutineMetadata* metadata; PathName moduleName; + string entryPoint; string info; - string table; - ExternalTrigger::Type type; GenericMap > > children; }; @@ -530,8 +489,12 @@ ModulesMap::~ModulesMap() //-------------------------------------- -void Engine::loadModule(const string& str, PathName* moduleName, string* entryPoint, string* info) +void Engine::loadModule(const IRoutineMetadata* metadata, PathName* moduleName, string* entryPoint) { + LocalStatus status; + const string str(metadata->getEntryPoint(&status)); + ThrowError::check(status.get()); + const size_t pos = str.find('!'); if (pos == string::npos) { @@ -562,7 +525,6 @@ void Engine::loadModule(const string& str, PathName* moduleName, string* entryPo *entryPoint = str.substr(pos + 1); size_t n = entryPoint->find('!'); - *info = (n == string::npos ? "" : entryPoint->substr(n + 1)); *entryPoint = (n == string::npos ? *entryPoint : entryPoint->substr(0, n)); MutexLockGuard guard(modulesMutex); @@ -612,7 +574,7 @@ template ObjType* ObjType* obj; if (!children.get(context, obj)) { - obj = getNode(nodes, moduleName, &sharedObj->metaInfo); + obj = getNode(nodes, moduleName, sharedObj->metadata, sharedObj->entryPoint); if (obj) children.put(context, obj); } @@ -634,11 +596,9 @@ template void Engine::deleteChildren( } -template T* Engine::findNode(T* nodes, - const PathName& moduleName, T2* params) +template T* Engine::findNode(T* nodes, const PathName& moduleName, + const string& entryPoint) { - const string entryPoint(params->entryPoint); - for (T* node = nodes; node; node = node->next) { if (node->module == moduleName && entryPoint == node->factory->getName()) @@ -658,11 +618,11 @@ template T* Engine::findNode(T* nodes, } -template T2* Engine::getNode(T* nodes, - const PathName& moduleName, T3* params) +template T2* Engine::getNode(T* nodes, const PathName& moduleName, + const IRoutineMetadata* metadata, const string& entryPoint) { - T* node = findNode(nodes, moduleName, params); - return node->factory->newItem(params); + T* node = findNode(nodes, moduleName, entryPoint); + return node->factory->newItem(metadata); } @@ -720,12 +680,11 @@ void FB_CALL Engine::closeAttachment(Error* error, ExternalContext* context) ExternalFunction* FB_CALL Engine::makeFunction(Error* error, ExternalContext* /*context*/, - const char* package, const char* name, const char* entryPoint, const char* body) + const IRoutineMetadata* metadata) { try { - return new SharedFunction(this, (package ? package : ""), name, - (entryPoint ? entryPoint : ""), (body ? body : "")); + return new SharedFunction(this, metadata); } catch (const ThrowError::Exception& e) { @@ -736,12 +695,11 @@ ExternalFunction* FB_CALL Engine::makeFunction(Error* error, ExternalContext* /* ExternalProcedure* FB_CALL Engine::makeProcedure(Error* error, ExternalContext* /*context*/, - const char* package, const char* name, const char* entryPoint, const char* body) + const IRoutineMetadata* metadata) { try { - return new SharedProcedure(this, (package ? package : ""), name, - (entryPoint ? entryPoint : ""), (body ? body : "")); + return new SharedProcedure(this, metadata); } catch (const ThrowError::Exception& e) { @@ -752,13 +710,11 @@ ExternalProcedure* FB_CALL Engine::makeProcedure(Error* error, ExternalContext* ExternalTrigger* FB_CALL Engine::makeTrigger(Error* error, ExternalContext* /*context*/, - const char* name, const char* entryPoint, const char* body, const char* table, - ExternalTrigger::Type type) + const IRoutineMetadata* metadata) { try { - return new SharedTrigger(this, name, (entryPoint ? entryPoint : ""), (body ? body : ""), - table, type); + return new SharedTrigger(this, metadata); } catch (const ThrowError::Exception& e) {