8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 10:43:03 +01:00
firebird-mirror/src/jrd/ExtEngineManager.h
2023-10-18 11:47:21 +03:00

363 lines
9.7 KiB
C++

/*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2008 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef JRD_EXT_ENGINE_MANAGER_H
#define JRD_EXT_ENGINE_MANAGER_H
#include "firebird/Interface.h"
#include <memory>
#include "../common/classes/array.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/GenericMap.h"
#include "../jrd/MetaName.h"
#include "../common/classes/NestConst.h"
#include "../common/classes/auto.h"
#include "../common/classes/rwlock.h"
#include "../common/classes/ImplementHelper.h"
#include "../common/StatementMetadata.h"
#include "../common/classes/GetPlugins.h"
struct dsc;
namespace Jrd {
class thread_db;
class jrd_prc;
class Request;
class jrd_tra;
class Attachment;
class CompilerScratch;
class Database;
class Format;
class Trigger;
class Function;
class DeclareVariableNode;
class StmtNode;
class ValueExprNode;
struct impure_value;
struct record_param;
class ExtEngineManager final : public Firebird::PermanentStorage
{
private:
class AttachmentImpl;
template <typename T> class ContextManager;
class TransactionImpl;
class RoutineMetadata final :
public Firebird::VersionedIface<Firebird::IRoutineMetadataImpl<RoutineMetadata, Firebird::CheckStatusWrapper> >,
public Firebird::PermanentStorage
{
public:
explicit RoutineMetadata(MemoryPool& pool)
: PermanentStorage(pool),
package(pool),
name(pool),
entryPoint(pool),
body(pool),
triggerTable(pool),
triggerType(0)
{
}
const char* getPackage(Firebird::CheckStatusWrapper* /*status*/) const
{
return package.nullStr();
}
const char* getName(Firebird::CheckStatusWrapper* /*status*/) const
{
return name.c_str();
}
const char* getEntryPoint(Firebird::CheckStatusWrapper* /*status*/) const
{
return entryPoint.c_str();
}
const char* getBody(Firebird::CheckStatusWrapper* /*status*/) const
{
return body.c_str();
}
Firebird::IMessageMetadata* getInputMetadata(Firebird::CheckStatusWrapper* /*status*/) const
{
return getMetadata(inputParameters);
}
Firebird::IMessageMetadata* getOutputMetadata(Firebird::CheckStatusWrapper* /*status*/) const
{
return getMetadata(outputParameters);
}
Firebird::IMessageMetadata* getTriggerMetadata(Firebird::CheckStatusWrapper* /*status*/) const
{
return getMetadata(triggerFields);
}
const char* getTriggerTable(Firebird::CheckStatusWrapper* /*status*/) const
{
return triggerTable.c_str();
}
unsigned getTriggerType(Firebird::CheckStatusWrapper* /*status*/) const
{
return triggerType;
}
public:
MetaName package;
MetaName name;
Firebird::string entryPoint;
Firebird::string body;
Firebird::RefPtr<Firebird::IMessageMetadata> inputParameters;
Firebird::RefPtr<Firebird::IMessageMetadata> outputParameters;
Firebird::RefPtr<Firebird::IMessageMetadata> triggerFields;
MetaName triggerTable;
unsigned triggerType;
private:
static Firebird::IMessageMetadata* getMetadata(const Firebird::IMessageMetadata* par)
{
Firebird::IMessageMetadata* rc = const_cast<Firebird::IMessageMetadata*>(par);
rc->addRef();
return rc;
}
};
class ExternalContextImpl :
public Firebird::VersionedIface<Firebird::IExternalContextImpl<ExternalContextImpl, Firebird::CheckStatusWrapper> >
{
friend class AttachmentImpl;
public:
ExternalContextImpl(thread_db* tdbb, Firebird::IExternalEngine* aEngine);
virtual ~ExternalContextImpl();
void releaseTransaction();
void setTransaction(thread_db* tdbb);
Firebird::IMaster* getMaster();
Firebird::IExternalEngine* getEngine(Firebird::CheckStatusWrapper* status);
Firebird::IAttachment* getAttachment(Firebird::CheckStatusWrapper* status);
Firebird::ITransaction* getTransaction(Firebird::CheckStatusWrapper* status);
const char* getUserName();
const char* getDatabaseName();
const char* getClientCharSet();
int obtainInfoCode();
void* getInfo(int code);
void* setInfo(int code, void* value);
private:
Firebird::IExternalEngine* engine;
Attachment* internalAttachment;
Firebird::ITransaction* internalTransaction;
Firebird::IAttachment* externalAttachment;
Firebird::ITransaction* externalTransaction;
Firebird::GenericMap<Firebird::NonPooled<int, void*> > miscInfo;
MetaName clientCharSet;
};
struct EngineAttachment
{
EngineAttachment(Firebird::IExternalEngine* aEngine, Jrd::Attachment* aAttachment)
: engine(aEngine),
attachment(aAttachment)
{
}
static bool greaterThan(const EngineAttachment& i1, const EngineAttachment& i2)
{
return (i1.engine > i2.engine) ||
(i1.engine == i2.engine && i1.attachment > i2.attachment);
}
Firebird::IExternalEngine* engine;
Jrd::Attachment* attachment;
};
struct EngineAttachmentInfo
{
EngineAttachmentInfo()
: engine(NULL),
context(NULL),
adminCharSet(0)
{
}
Firebird::IExternalEngine* engine;
Firebird::AutoPtr<ExternalContextImpl> context;
USHORT adminCharSet;
};
public:
class ExtRoutine
{
public:
ExtRoutine(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::IExternalEngine* aEngine, RoutineMetadata* aMetadata);
private:
class PluginDeleter
{
public:
void operator()(Firebird::IPluginBase* ptr);
};
protected:
ExtEngineManager* extManager;
std::unique_ptr<Firebird::IExternalEngine, PluginDeleter> engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
Database* database;
};
class Function : public ExtRoutine
{
public:
Function(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::IExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::IExternalFunction* aFunction,
const Jrd::Function* aUdf);
~Function();
void execute(thread_db* tdbb, UCHAR* inMsg, UCHAR* outMsg) const;
private:
Firebird::IExternalFunction* function;
const Jrd::Function* udf;
};
class ResultSet;
class Procedure : public ExtRoutine
{
public:
Procedure(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::IExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::IExternalProcedure* aProcedure,
const jrd_prc* aPrc);
~Procedure();
ResultSet* open(thread_db* tdbb, UCHAR* inMsg, UCHAR* outMsg) const;
private:
Firebird::IExternalProcedure* procedure;
const jrd_prc* prc;
friend class ResultSet;
};
class ResultSet
{
public:
ResultSet(thread_db* tdbb, UCHAR* inMsg, UCHAR* outMsg, const Procedure* aProcedure);
~ResultSet();
bool fetch(thread_db* tdbb);
private:
const Procedure* procedure;
Attachment* attachment;
bool firstFetch;
EngineAttachmentInfo* attInfo;
Firebird::IExternalResultSet* resultSet;
USHORT charSet;
};
class Trigger : public ExtRoutine
{
public:
Trigger(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, ExtEngineManager* aExtManager,
Firebird::IExternalEngine* aEngine, RoutineMetadata* aMetadata,
Firebird::IExternalTrigger* aTrigger, const Jrd::Trigger* aTrg);
~Trigger();
void execute(thread_db* tdbb, Request* request, unsigned action,
record_param* oldRpb, record_param* newRpb) const;
private:
void setupComputedFields(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb);
void setValues(thread_db* tdbb, Request* request, Firebird::Array<UCHAR>& msgBuffer, record_param* rpb) const;
public:
Firebird::Array<NestConst<StmtNode>> computedStatements;
private:
Firebird::AutoPtr<Format> format;
Firebird::IExternalTrigger* trigger;
const Jrd::Trigger* trg;
Firebird::Array<USHORT> fieldsPos;
Firebird::Array<const DeclareVariableNode*> varDecls;
USHORT computedCount;
};
public:
explicit ExtEngineManager(MemoryPool& p);
~ExtEngineManager();
public:
static void initialize();
public:
void closeAttachment(thread_db* tdbb, Attachment* attachment);
void makeFunction(thread_db* tdbb, CompilerScratch* csb, Jrd::Function* udf,
const MetaName& engine, const Firebird::string& entryPoint,
const Firebird::string& body);
void makeProcedure(thread_db* tdbb, CompilerScratch* csb, jrd_prc* prc,
const MetaName& engine, const Firebird::string& entryPoint,
const Firebird::string& body);
void makeTrigger(thread_db* tdbb, CompilerScratch* csb, Jrd::Trigger* trg,
const MetaName& engine, const Firebird::string& entryPoint,
const Firebird::string& body, unsigned type);
private:
Firebird::IExternalEngine* getEngine(thread_db* tdbb,
const MetaName& name);
EngineAttachmentInfo* getEngineAttachment(thread_db* tdbb,
const MetaName& name);
EngineAttachmentInfo* getEngineAttachment(thread_db* tdbb,
Firebird::IExternalEngine* engine, bool closing = false);
void setupAdminCharSet(thread_db* tdbb, Firebird::IExternalEngine* engine,
EngineAttachmentInfo* attInfo);
private:
typedef Firebird::GenericMap<Firebird::Pair<
Firebird::Left<MetaName, Firebird::IExternalEngine*> > > EnginesMap;
typedef Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<
EngineAttachment, EngineAttachmentInfo*> >, EngineAttachment> EnginesAttachmentsMap;
Firebird::RWLock enginesLock;
EnginesMap engines;
EnginesAttachmentsMap enginesAttachments;
};
} // namespace Jrd
#endif // JRD_EXT_ENGINE_MANAGER_H