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

Added IRoutineMetadata to external engines.

Not well tested:
1) EE is broken after shared page cache.
2) Semantics of addRef/release still keeps changing in developers minds.
This commit is contained in:
asfernandes 2011-05-15 15:37:11 +00:00
parent 9083c98e8b
commit 983686d71c
7 changed files with 281 additions and 149 deletions

View File

@ -30,6 +30,8 @@ using namespace Firebird;
using namespace Firebird::Udr; using namespace Firebird::Udr;
typedef IMaster* (ISC_EXPORT *FuncGetMasterInterface)();
typedef ISC_LONG (ISC_EXPORT_VARARG *FuncEventBlock)(ISC_UCHAR**, ISC_UCHAR**, ISC_USHORT, ...); typedef ISC_LONG (ISC_EXPORT_VARARG *FuncEventBlock)(ISC_UCHAR**, ISC_UCHAR**, ISC_USHORT, ...);
typedef ISC_STATUS (ISC_EXPORT *FuncWaitForEvent)(ISC_STATUS*, isc_db_handle*, typedef ISC_STATUS (ISC_EXPORT *FuncWaitForEvent)(ISC_STATUS*, isc_db_handle*,
short, const ISC_UCHAR*, ISC_UCHAR*); 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*); unsigned short, const ISC_SCHAR*, unsigned short, XSQLDA*);
namespace
{
template <typename T>
class AutoDispose
{
public:
AutoDispose<T>(T* aPtr = NULL)
: ptr(aPtr)
{
}
~AutoDispose()
{
clear();
}
AutoDispose<T>& 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<T>(AutoDispose<T>&);
void operator =(AutoDispose<T>&);
private:
T* ptr;
};
}
/*** /***
create function wait_event ( create function wait_event (
event_name varchar(31) character set ascii event_name varchar(31) character set ascii
@ -135,6 +218,7 @@ private:
isc_stmt_handle stmtHandle; isc_stmt_handle stmtHandle;
// ISC entry points // ISC entry points
FuncGetMasterInterface funcGetMasterInterface;
FuncDsqlAllocateStatement funcDsqlAllocateStatement; FuncDsqlAllocateStatement funcDsqlAllocateStatement;
FuncDsqlDescribe funcDsqlDescribe; FuncDsqlDescribe funcDsqlDescribe;
FuncDsqlDescribeBind funcDsqlDescribeBind; FuncDsqlDescribeBind funcDsqlDescribeBind;
@ -246,6 +330,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val
return; return;
// ISC entry points // ISC entry points
funcGetMasterInterface = (FuncGetMasterInterface) getEntryPoint(context, "fb_get_master_interface");
funcDsqlAllocateStatement = (FuncDsqlAllocateStatement) funcDsqlAllocateStatement = (FuncDsqlAllocateStatement)
getEntryPoint(context, "isc_dsql_allocate_statement"); getEntryPoint(context, "isc_dsql_allocate_statement");
funcDsqlDescribe = (FuncDsqlDescribe) getEntryPoint(context, "isc_dsql_describe"); 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 = ?", "select data_source from replicate_config where name = ?",
SQL_DIALECT_CURRENT, NULL), statusVector); SQL_DIALECT_CURRENT, NULL), statusVector);
AutoDispose<IMaster> master(funcGetMasterInterface());
AutoDispose<IStatus> 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<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]); inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
inSqlDa->version = SQLDA_VERSION1; inSqlDa->version = SQLDA_VERSION1;
inSqlDa->sqln = 1; inSqlDa->sqln = 1;
ThrowError::check(funcDsqlDescribeBind(statusVector, &stmtHandle, SQL_DIALECT_CURRENT, inSqlDa), ThrowError::check(funcDsqlDescribeBind(statusVector, &stmtHandle, SQL_DIALECT_CURRENT, inSqlDa),
statusVector); statusVector);
inSqlDa->sqlvar[0].sqldata = new char[sizeof(short) + inSqlDa->sqlvar[0].sqllen]; 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); strncpy(inSqlDa->sqlvar[0].sqldata + sizeof(short), info, inSqlDa->sqlvar[0].sqllen);
*reinterpret_cast<short*>(inSqlDa->sqlvar[0].sqldata) = strlen(metaInfo->info); *reinterpret_cast<short*>(inSqlDa->sqlvar[0].sqldata) = strlen(info);
XSQLDA* outSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]); XSQLDA* outSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
outSqlDa->version = SQLDA_VERSION1; outSqlDa->version = SQLDA_VERSION1;
@ -304,7 +408,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val
const char* name = val->getName(ThrowError()); const char* name = val->getName(ThrowError());
strcat(buffer, " p"); 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, strcat(buffer,
@ -313,7 +417,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val
"begin\n" "begin\n"
" execute statement ('insert into \""); " execute statement ('insert into \"");
strcat(buffer, metaInfo->table); strcat(buffer, table);
strcat(buffer, "\" ("); strcat(buffer, "\" (");
for (int i = 1; i <= count; ++i) for (int i = 1; i <= count; ++i)
@ -449,7 +553,7 @@ FB_UDR_BEGIN_TRIGGER(replicate)
{ {
case SQL_VARYING: case SQL_VARYING:
{ {
uint len; unsigned len;
const char* s = val->getString(ThrowError(), &len); const char* s = val->getString(ThrowError(), &len);
*reinterpret_cast<unsigned short*>(var->sqldata) = len; *reinterpret_cast<unsigned short*>(var->sqldata) = len;
memcpy(var->sqldata + sizeof(unsigned short), s, len); memcpy(var->sqldata + sizeof(unsigned short), s, len);

View File

@ -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) // In SuperServer, shared by all attachments to one database and disposed when last (non-external)
// user attachment to the database is closed. // user attachment to the database is closed.
class ExternalEngine : public IPluginBase class ExternalEngine : public IPluginBase
@ -175,12 +188,11 @@ public:
// Called when engine wants to load object in the cache. Objects are disposed when // Called when engine wants to load object in the cache. Objects are disposed when
// going out of the cache. // going out of the cache.
virtual ExternalFunction* FB_CALL makeFunction(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) = 0; const IRoutineMetadata* metadata) = 0;
virtual ExternalProcedure* FB_CALL makeProcedure(Error* error, ExternalContext* context, 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, virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context,
const char* name, const char* entryPoint, const char* body, const IRoutineMetadata* metadata) = 0;
const char* table, ExternalTrigger::Type type) = 0;
}; };
#define FB_EXTERNAL_ENGINE_VERSION (FB_PLUGIN_VERSION + 7) #define FB_EXTERNAL_ENGINE_VERSION (FB_PLUGIN_VERSION + 7)

View File

@ -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 // 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. // registered. When UDR engine is going to load a routine, it calls newItem.
@ -59,21 +41,21 @@ class FunctionFactory
{ {
public: public:
virtual const char* FB_CALL getName() = 0; 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 class ProcedureFactory
{ {
public: public:
virtual const char* FB_CALL getName() = 0; 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 class TriggerFactory
{ {
public: public:
virtual const char* FB_CALL getName() = 0; virtual const char* FB_CALL getName() = 0;
virtual ExternalTrigger* FB_CALL newItem(TriggerMetaInfo* metaInfo) = 0; virtual ExternalTrigger* FB_CALL newItem(const IRoutineMetadata* metadata) = 0;
}; };

View File

@ -503,7 +503,7 @@ public:
} }
public: public:
MetaInfo* metaInfo; const IRoutineMetadata* metadata;
}; };
@ -525,7 +525,7 @@ public:
} }
public: public:
MetaInfo* metaInfo; const IRoutineMetadata* metadata;
}; };
@ -547,7 +547,7 @@ public:
} }
public: public:
TriggerMetaInfo* metaInfo; const IRoutineMetadata* metadata;
}; };
@ -566,10 +566,10 @@ public:
return name; return name;
} }
virtual ExternalFunction* FB_CALL newItem(MetaInfo* metaInfo) virtual ExternalFunction* FB_CALL newItem(const IRoutineMetadata* metadata)
{ {
Function* function = new T(); Function* function = new T();
function->metaInfo = metaInfo; function->metadata = metadata;
return function; return function;
} }
@ -593,10 +593,10 @@ public:
return name; return name;
} }
virtual ExternalProcedure* FB_CALL newItem(MetaInfo* metaInfo) virtual ExternalProcedure* FB_CALL newItem(const IRoutineMetadata* metadata)
{ {
Procedure* procedure = new T(); Procedure* procedure = new T();
procedure->metaInfo = metaInfo; procedure->metadata = metadata;
return procedure; return procedure;
} }
@ -620,10 +620,10 @@ public:
return name; return name;
} }
virtual ExternalTrigger* FB_CALL newItem(TriggerMetaInfo* metaInfo) virtual ExternalTrigger* FB_CALL newItem(const IRoutineMetadata* metadata)
{ {
Trigger* trigger = new T(); Trigger* trigger = new T();
trigger->metaInfo = metaInfo; trigger->metadata = metadata;
return trigger; return trigger;
} }

View File

@ -286,10 +286,11 @@ void* FB_CALL ExtEngineManager::ExternalContextImpl::setInfo(int code, void* val
ExtEngineManager::Function::Function(thread_db* tdbb, ExtEngineManager* aExtManager, ExtEngineManager::Function::Function(thread_db* tdbb, ExtEngineManager* aExtManager,
ExternalEngine* aEngine, ExternalFunction* aFunction, ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalFunction* aFunction,
const Jrd::Function* aUdf) const Jrd::Function* aUdf)
: extManager(aExtManager), : extManager(aExtManager),
engine(aEngine), engine(aEngine),
metadata(aMetadata),
function(aFunction), function(aFunction),
udf(aUdf), udf(aUdf),
database(tdbb->getDatabase()) database(tdbb->getDatabase())
@ -384,10 +385,11 @@ void ExtEngineManager::Function::execute(thread_db* tdbb, const NestValueArray&
ExtEngineManager::Procedure::Procedure(thread_db* tdbb, ExtEngineManager* aExtManager, ExtEngineManager::Procedure::Procedure(thread_db* tdbb, ExtEngineManager* aExtManager,
ExternalEngine* aEngine, ExternalProcedure* aProcedure, ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalProcedure* aProcedure,
const jrd_prc* aPrc) const jrd_prc* aPrc)
: extManager(aExtManager), : extManager(aExtManager),
engine(aEngine), engine(aEngine),
metadata(aMetadata),
procedure(aProcedure), procedure(aProcedure),
prc(aPrc), prc(aPrc),
database(tdbb->getDatabase()) database(tdbb->getDatabase())
@ -467,10 +469,11 @@ bool ExtEngineManager::ResultSet::fetch(thread_db* tdbb)
ExtEngineManager::Trigger::Trigger(thread_db* tdbb, ExtEngineManager* aExtManager, ExtEngineManager::Trigger::Trigger(thread_db* tdbb, ExtEngineManager* aExtManager,
ExternalEngine* aEngine, ExternalTrigger* aTrigger, ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalTrigger* aTrigger,
const Jrd::Trigger* aTrg) const Jrd::Trigger* aTrg)
: extManager(aExtManager), : extManager(aExtManager),
engine(aEngine), engine(aEngine),
metadata(aMetadata),
trigger(aTrigger), trigger(aTrigger),
trg(aTrg), trg(aTrg),
database(tdbb->getDatabase()) database(tdbb->getDatabase())
@ -651,14 +654,19 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons
CallerName(obj_udf, udf->getName().identifier) : CallerName(obj_udf, udf->getName().identifier) :
CallerName(obj_package_header, udf->getName().package))); CallerName(obj_package_header, udf->getName().package)));
MemoryPool& pool = *tdbb->getDefaultPool();
AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
metadata->package = udf->getName().package;
metadata->name = udf->getName().identifier;
metadata->entryPoint = entryPointTrimmed;
metadata->body = body;
ExternalFunction* externalFunction; ExternalFunction* externalFunction;
{ // scope { // scope
Attachment::Checkout attCout(tdbb->getAttachment()); Attachment::Checkout attCout(tdbb->getAttachment());
externalFunction = attInfo->engine->makeFunction(RaiseError(), externalFunction = attInfo->engine->makeFunction(RaiseError(), attInfo->context, metadata);
attInfo->context, udf->getName().package.nullStr(), udf->getName().identifier.c_str(),
entryPointTrimmed.nullStr(), body.nullStr());
if (!externalFunction) if (!externalFunction)
{ {
@ -670,7 +678,8 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons
try 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 (...) catch (...)
{ {
@ -693,14 +702,19 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co
CallerName(obj_procedure, prc->getName().identifier) : CallerName(obj_procedure, prc->getName().identifier) :
CallerName(obj_package_header, prc->getName().package))); CallerName(obj_package_header, prc->getName().package)));
MemoryPool& pool = *tdbb->getDefaultPool();
AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
metadata->package = prc->getName().package;
metadata->name = prc->getName().identifier;
metadata->entryPoint = entryPointTrimmed;
metadata->body = body;
ExternalProcedure* externalProcedure; ExternalProcedure* externalProcedure;
{ // scope { // scope
Attachment::Checkout attCout(tdbb->getAttachment()); Attachment::Checkout attCout(tdbb->getAttachment());
externalProcedure = attInfo->engine->makeProcedure(RaiseError(), externalProcedure = attInfo->engine->makeProcedure(RaiseError(), attInfo->context, metadata);
attInfo->context, prc->getName().package.nullStr(), prc->getName().identifier.c_str(),
entryPointTrimmed.nullStr(), body.nullStr());
if (!externalProcedure) if (!externalProcedure)
{ {
@ -712,7 +726,8 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co
try 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 (...) catch (...)
{ {
@ -729,22 +744,25 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
string entryPointTrimmed = entryPoint; string entryPointTrimmed = entryPoint;
entryPointTrimmed.trim(); entryPointTrimmed.trim();
MetaName relationNameTrimmed;
if (trg->relation)
relationNameTrimmed = trg->relation->rel_name;
EngineAttachmentInfo* attInfo = getEngineAttachment(tdbb, engine); EngineAttachmentInfo* attInfo = getEngineAttachment(tdbb, engine);
ContextManager<ExternalTrigger> ctxManager(tdbb, attInfo, attInfo->adminCharSet, ContextManager<ExternalTrigger> ctxManager(tdbb, attInfo, attInfo->adminCharSet,
CallerName(obj_trigger, trg->name)); CallerName(obj_trigger, trg->name));
MemoryPool& pool = *tdbb->getDefaultPool();
AutoPtr<RoutineMetadata> 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; ExternalTrigger* externalTrigger;
{ // scope { // scope
Attachment::Checkout attCout(tdbb->getAttachment()); Attachment::Checkout attCout(tdbb->getAttachment());
externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context, externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context, metadata);
trg->name.c_str(), entryPointTrimmed.nullStr(), body.nullStr(),
relationNameTrimmed.c_str(), type);
if (!externalTrigger) if (!externalTrigger)
{ {
@ -755,7 +773,8 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
try 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 (...) catch (...)
{ {

View File

@ -61,6 +61,59 @@ private:
template <typename T> class ContextManager; template <typename T> class ContextManager;
class TransactionImpl; 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 class ExternalContextImpl : public Firebird::ExternalContext
{ {
friend class AttachmentImpl; friend class AttachmentImpl;
@ -130,6 +183,7 @@ public:
public: public:
Function(thread_db* tdbb, ExtEngineManager* aExtManager, Function(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::ExternalEngine* aEngine, Firebird::ExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::ExternalFunction* aFunction, Firebird::ExternalFunction* aFunction,
const Jrd::Function* aUdf); const Jrd::Function* aUdf);
~Function(); ~Function();
@ -140,6 +194,7 @@ public:
private: private:
ExtEngineManager* extManager; ExtEngineManager* extManager;
Firebird::ExternalEngine* engine; Firebird::ExternalEngine* engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
Firebird::ExternalFunction* function; Firebird::ExternalFunction* function;
const Jrd::Function* udf; const Jrd::Function* udf;
Database* database; Database* database;
@ -152,6 +207,7 @@ public:
public: public:
Procedure(thread_db* tdbb, ExtEngineManager* aExtManager, Procedure(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::ExternalEngine* aEngine, Firebird::ExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::ExternalProcedure* aProcedure, Firebird::ExternalProcedure* aProcedure,
const jrd_prc* aPrc); const jrd_prc* aPrc);
~Procedure(); ~Procedure();
@ -161,6 +217,7 @@ public:
private: private:
ExtEngineManager* extManager; ExtEngineManager* extManager;
Firebird::ExternalEngine* engine; Firebird::ExternalEngine* engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
Firebird::ExternalProcedure* procedure; Firebird::ExternalProcedure* procedure;
const jrd_prc* prc; const jrd_prc* prc;
Database* database; Database* database;
@ -191,6 +248,7 @@ public:
public: public:
Trigger(thread_db* tdbb, ExtEngineManager* aExtManager, Trigger(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::ExternalEngine* aEngine, Firebird::ExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::ExternalTrigger* aTrigger, Firebird::ExternalTrigger* aTrigger,
const Jrd::Trigger* aTrg); const Jrd::Trigger* aTrg);
~Trigger(); ~Trigger();
@ -205,6 +263,7 @@ public:
ExtEngineManager* extManager; ExtEngineManager* extManager;
Firebird::ExternalEngine* engine; Firebird::ExternalEngine* engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
Firebird::ExternalTrigger* trigger; Firebird::ExternalTrigger* trigger;
const Jrd::Trigger* trg; const Jrd::Trigger* trg;
Database* database; Database* database;

View File

@ -36,6 +36,7 @@
#include "../common/os/mod_loader.h" #include "../common/os/mod_loader.h"
#include "../common/os/path_utils.h" #include "../common/os/path_utils.h"
#include "../common/classes/ImplementHelper.h" #include "../common/classes/ImplementHelper.h"
#include "../common/StatusHolder.h"
namespace Firebird namespace Firebird
@ -130,7 +131,7 @@ public:
} }
public: public:
void loadModule(const string& str, PathName* moduleName, string* entryPoint, string* info); void loadModule(const IRoutineMetadata* metadata, PathName* moduleName, string* entryPoint);
template <typename NodeType, typename ObjType, typename SharedObjType> ObjType* getChild( template <typename NodeType, typename ObjType, typename SharedObjType> ObjType* getChild(
GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children, SharedObjType* sharedObj, GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children, SharedObjType* sharedObj,
ExternalContext* context, NodeType* nodes, SortedArray<SharedObjType*>& sharedObjs, ExternalContext* context, NodeType* nodes, SortedArray<SharedObjType*>& sharedObjs,
@ -138,12 +139,12 @@ public:
template <typename ObjType> void deleteChildren( template <typename ObjType> void deleteChildren(
GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children); GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children);
template <typename T, typename T2> T* findNode(T* nodes, const PathName& moduleName, template <typename T> T* findNode(T* nodes, const PathName& moduleName,
T2* metaInfo); const string& entryPoint);
private: private:
template <typename T, typename T2, typename T3> T2* getNode(T* nodes, const PathName& moduleName, template <typename T, typename T2> T2* getNode(T* nodes, const PathName& moduleName,
T3* metaInfo); const IRoutineMetadata* metadata, const string& entryPoint);
public: public:
virtual int FB_CALL getVersion(Error* error); 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 openAttachment(Error* error, ExternalContext* context);
virtual void FB_CALL closeAttachment(Error* error, ExternalContext* context); virtual void FB_CALL closeAttachment(Error* error, ExternalContext* context);
virtual ExternalFunction* FB_CALL makeFunction(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, 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, virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context,
const char* name, const char* entryPoint, const char* body, const char* table, const IRoutineMetadata* metadata);
ExternalTrigger::Type type);
public: public:
virtual void FB_CALL dispose(Error* error); virtual void FB_CALL dispose(Error* error);
@ -205,25 +205,16 @@ static TriggerNode* registeredTriggers = NULL;
class SharedFunction : public ExternalFunction class SharedFunction : public ExternalFunction
{ {
public: public:
SharedFunction(Engine* aEngine, const string& aPackage, const string& aName, SharedFunction(Engine* aEngine, const IRoutineMetadata* aMetadata)
const string& aEntryPoint, const string& aBody)
: engine(aEngine), : engine(aEngine),
package(*getDefaultMemoryPool(), aPackage), metadata(aMetadata),
name(*getDefaultMemoryPool(), aName),
entryPoint(*getDefaultMemoryPool()),
body(*getDefaultMemoryPool(), aBody),
moduleName(*getDefaultMemoryPool()), moduleName(*getDefaultMemoryPool()),
entryPoint(*getDefaultMemoryPool()),
info(*getDefaultMemoryPool()), info(*getDefaultMemoryPool()),
children(*getDefaultMemoryPool()) children(*getDefaultMemoryPool())
{ {
engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info); engine->loadModule(metadata, &moduleName, &entryPoint);
metaInfo.package = package.nullStr(); engine->findNode<FunctionNode>(registeredFunctions, moduleName, entryPoint);
metaInfo.name = name.c_str();
metaInfo.entryPoint = entryPoint.c_str();
metaInfo.body = body.c_str();
metaInfo.info = info.c_str();
engine->findNode<FunctionNode, MetaInfo>(registeredFunctions, moduleName, &metaInfo);
} }
virtual ~SharedFunction() virtual ~SharedFunction()
@ -266,13 +257,10 @@ public:
} }
public: public:
MetaInfo metaInfo;
Engine* engine; Engine* engine;
string package; const IRoutineMetadata* metadata;
string name;
string entryPoint;
string body;
PathName moduleName; PathName moduleName;
string entryPoint;
string info; string info;
GenericMap<Pair<NonPooled<ExternalContext*, ExternalFunction*> > > children; GenericMap<Pair<NonPooled<ExternalContext*, ExternalFunction*> > > children;
}; };
@ -284,25 +272,15 @@ public:
class SharedProcedure : public ExternalProcedure class SharedProcedure : public ExternalProcedure
{ {
public: public:
SharedProcedure(Engine* aEngine, const string& aPackage, const string& aName, SharedProcedure(Engine* aEngine, const IRoutineMetadata* aMetadata)
const string& aEntryPoint, const string& aBody)
: engine(aEngine), : engine(aEngine),
package(*getDefaultMemoryPool(), aPackage),
name(*getDefaultMemoryPool(), aName),
entryPoint(*getDefaultMemoryPool(), aEntryPoint),
body(*getDefaultMemoryPool(), aBody),
moduleName(*getDefaultMemoryPool()), moduleName(*getDefaultMemoryPool()),
entryPoint(*getDefaultMemoryPool()),
info(*getDefaultMemoryPool()), info(*getDefaultMemoryPool()),
children(*getDefaultMemoryPool()) children(*getDefaultMemoryPool())
{ {
engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info); engine->loadModule(metadata, &moduleName, &entryPoint);
metaInfo.package = package.nullStr(); engine->findNode<ProcedureNode>(registeredProcedures, moduleName, entryPoint);
metaInfo.name = name.c_str();
metaInfo.entryPoint = entryPoint.c_str();
metaInfo.body = body.c_str();
metaInfo.info = info.c_str();
engine->findNode<ProcedureNode, MetaInfo>(registeredProcedures, moduleName, &metaInfo);
} }
virtual ~SharedProcedure() virtual ~SharedProcedure()
@ -352,13 +330,10 @@ public:
} }
public: public:
MetaInfo metaInfo;
Engine* engine; Engine* engine;
string package; const IRoutineMetadata* metadata;
string name;
string entryPoint;
string body;
PathName moduleName; PathName moduleName;
string entryPoint;
string info; string info;
GenericMap<Pair<NonPooled<ExternalContext*, ExternalProcedure*> > > children; GenericMap<Pair<NonPooled<ExternalContext*, ExternalProcedure*> > > children;
}; };
@ -370,28 +345,16 @@ public:
class SharedTrigger : public ExternalTrigger class SharedTrigger : public ExternalTrigger
{ {
public: public:
SharedTrigger(Engine* aEngine, const string& aName, const string& aEntryPoint, SharedTrigger(Engine* aEngine, const IRoutineMetadata* aMetadata)
const string& aBody, const string& aTable, ExternalTrigger::Type aType)
: engine(aEngine), : engine(aEngine),
name(*getDefaultMemoryPool(), aName), metadata(aMetadata),
entryPoint(*getDefaultMemoryPool(), aEntryPoint),
body(*getDefaultMemoryPool(), aBody),
moduleName(*getDefaultMemoryPool()), moduleName(*getDefaultMemoryPool()),
entryPoint(*getDefaultMemoryPool()),
info(*getDefaultMemoryPool()), info(*getDefaultMemoryPool()),
table(*getDefaultMemoryPool(), aTable),
type(aType),
children(*getDefaultMemoryPool()) children(*getDefaultMemoryPool())
{ {
engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info); engine->loadModule(metadata, &moduleName, &entryPoint);
metaInfo.package = NULL; engine->findNode<TriggerNode>(registeredTriggers, moduleName, entryPoint);
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<TriggerNode, TriggerMetaInfo>(registeredTriggers, moduleName, &metaInfo);
} }
virtual ~SharedTrigger() virtual ~SharedTrigger()
@ -434,15 +397,11 @@ public:
} }
public: public:
TriggerMetaInfo metaInfo;
Engine* engine; Engine* engine;
string name; const IRoutineMetadata* metadata;
string entryPoint;
string body;
PathName moduleName; PathName moduleName;
string entryPoint;
string info; string info;
string table;
ExternalTrigger::Type type;
GenericMap<Pair<NonPooled<ExternalContext*, ExternalTrigger*> > > children; GenericMap<Pair<NonPooled<ExternalContext*, ExternalTrigger*> > > 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('!'); const size_t pos = str.find('!');
if (pos == string::npos) if (pos == string::npos)
{ {
@ -562,7 +525,6 @@ void Engine::loadModule(const string& str, PathName* moduleName, string* entryPo
*entryPoint = str.substr(pos + 1); *entryPoint = str.substr(pos + 1);
size_t n = entryPoint->find('!'); size_t n = entryPoint->find('!');
*info = (n == string::npos ? "" : entryPoint->substr(n + 1));
*entryPoint = (n == string::npos ? *entryPoint : entryPoint->substr(0, n)); *entryPoint = (n == string::npos ? *entryPoint : entryPoint->substr(0, n));
MutexLockGuard guard(modulesMutex); MutexLockGuard guard(modulesMutex);
@ -612,7 +574,7 @@ template <typename NodeType, typename ObjType, typename SharedObjType> ObjType*
ObjType* obj; ObjType* obj;
if (!children.get(context, obj)) if (!children.get(context, obj))
{ {
obj = getNode<NodeType, ObjType>(nodes, moduleName, &sharedObj->metaInfo); obj = getNode<NodeType, ObjType>(nodes, moduleName, sharedObj->metadata, sharedObj->entryPoint);
if (obj) if (obj)
children.put(context, obj); children.put(context, obj);
} }
@ -634,11 +596,9 @@ template <typename ObjType> void Engine::deleteChildren(
} }
template <typename T, typename T2> T* Engine::findNode(T* nodes, template <typename T> T* Engine::findNode(T* nodes, const PathName& moduleName,
const PathName& moduleName, T2* params) const string& entryPoint)
{ {
const string entryPoint(params->entryPoint);
for (T* node = nodes; node; node = node->next) for (T* node = nodes; node; node = node->next)
{ {
if (node->module == moduleName && entryPoint == node->factory->getName()) if (node->module == moduleName && entryPoint == node->factory->getName())
@ -658,11 +618,11 @@ template <typename T, typename T2> T* Engine::findNode(T* nodes,
} }
template <typename T, typename T2, typename T3> T2* Engine::getNode(T* nodes, template <typename T, typename T2> T2* Engine::getNode(T* nodes, const PathName& moduleName,
const PathName& moduleName, T3* params) const IRoutineMetadata* metadata, const string& entryPoint)
{ {
T* node = findNode<T, T3>(nodes, moduleName, params); T* node = findNode<T>(nodes, moduleName, entryPoint);
return node->factory->newItem(params); 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*/, 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 try
{ {
return new SharedFunction(this, (package ? package : ""), name, return new SharedFunction(this, metadata);
(entryPoint ? entryPoint : ""), (body ? body : ""));
} }
catch (const ThrowError::Exception& e) 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*/, 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 try
{ {
return new SharedProcedure(this, (package ? package : ""), name, return new SharedProcedure(this, metadata);
(entryPoint ? entryPoint : ""), (body ? body : ""));
} }
catch (const ThrowError::Exception& e) 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*/, ExternalTrigger* FB_CALL Engine::makeTrigger(Error* error, ExternalContext* /*context*/,
const char* name, const char* entryPoint, const char* body, const char* table, const IRoutineMetadata* metadata)
ExternalTrigger::Type type)
{ {
try try
{ {
return new SharedTrigger(this, name, (entryPoint ? entryPoint : ""), (body ? body : ""), return new SharedTrigger(this, metadata);
table, type);
} }
catch (const ThrowError::Exception& e) catch (const ThrowError::Exception& e)
{ {