mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +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:
parent
9083c98e8b
commit
983686d71c
@ -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 <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 (
|
||||
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<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->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<short*>(inSqlDa->sqlvar[0].sqldata) = strlen(metaInfo->info);
|
||||
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;
|
||||
@ -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<unsigned short*>(var->sqldata) = len;
|
||||
memcpy(var->sqldata + sizeof(unsigned short), s, len);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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<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;
|
||||
|
||||
{ // 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<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;
|
||||
|
||||
{ // 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<ExternalTrigger> ctxManager(tdbb, attInfo, attInfo->adminCharSet,
|
||||
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;
|
||||
|
||||
{ // 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 (...)
|
||||
{
|
||||
|
@ -61,6 +61,59 @@ private:
|
||||
template <typename T> 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<RoutineMetadata> 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<RoutineMetadata> 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<RoutineMetadata> metadata;
|
||||
Firebird::ExternalTrigger* trigger;
|
||||
const Jrd::Trigger* trg;
|
||||
Database* database;
|
||||
|
@ -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 <typename NodeType, typename ObjType, typename SharedObjType> ObjType* getChild(
|
||||
GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children, SharedObjType* sharedObj,
|
||||
ExternalContext* context, NodeType* nodes, SortedArray<SharedObjType*>& sharedObjs,
|
||||
@ -138,12 +139,12 @@ public:
|
||||
template <typename ObjType> void deleteChildren(
|
||||
GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children);
|
||||
|
||||
template <typename T, typename T2> T* findNode(T* nodes, const PathName& moduleName,
|
||||
T2* metaInfo);
|
||||
template <typename T> T* findNode(T* nodes, const PathName& moduleName,
|
||||
const string& entryPoint);
|
||||
|
||||
private:
|
||||
template <typename T, typename T2, typename T3> T2* getNode(T* nodes, const PathName& moduleName,
|
||||
T3* metaInfo);
|
||||
template <typename T, typename T2> 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<FunctionNode, MetaInfo>(registeredFunctions, moduleName, &metaInfo);
|
||||
engine->loadModule(metadata, &moduleName, &entryPoint);
|
||||
engine->findNode<FunctionNode>(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<Pair<NonPooled<ExternalContext*, ExternalFunction*> > > 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<ProcedureNode, MetaInfo>(registeredProcedures, moduleName, &metaInfo);
|
||||
engine->loadModule(metadata, &moduleName, &entryPoint);
|
||||
engine->findNode<ProcedureNode>(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<Pair<NonPooled<ExternalContext*, ExternalProcedure*> > > 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<TriggerNode, TriggerMetaInfo>(registeredTriggers, moduleName, &metaInfo);
|
||||
engine->loadModule(metadata, &moduleName, &entryPoint);
|
||||
engine->findNode<TriggerNode>(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<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('!');
|
||||
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 <typename NodeType, typename ObjType, typename SharedObjType> ObjType*
|
||||
ObjType* 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)
|
||||
children.put(context, obj);
|
||||
}
|
||||
@ -634,11 +596,9 @@ template <typename ObjType> void Engine::deleteChildren(
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename T2> T* Engine::findNode(T* nodes,
|
||||
const PathName& moduleName, T2* params)
|
||||
template <typename T> 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 <typename T, typename T2> T* Engine::findNode(T* nodes,
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename T2, typename T3> T2* Engine::getNode(T* nodes,
|
||||
const PathName& moduleName, T3* params)
|
||||
template <typename T, typename T2> T2* Engine::getNode(T* nodes, const PathName& moduleName,
|
||||
const IRoutineMetadata* metadata, const string& entryPoint)
|
||||
{
|
||||
T* node = findNode<T, T3>(nodes, moduleName, params);
|
||||
return node->factory->newItem(params);
|
||||
T* node = findNode<T>(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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user