ExtEngineManager.cpp (Firebird-3.0.2.32703-0.tar.bz2) | : | ExtEngineManager.cpp (Firebird-3.0.4.33054-0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 61 | skipping to change at line 61 | |||
#include "../common/config/config.h" | #include "../common/config/config.h" | |||
#include "../common/ScanDir.h" | #include "../common/ScanDir.h" | |||
#include "../common/utils_proto.h" | #include "../common/utils_proto.h" | |||
#include "../common/classes/GetPlugins.h" | #include "../common/classes/GetPlugins.h" | |||
using namespace Firebird; | using namespace Firebird; | |||
using namespace Jrd; | using namespace Jrd; | |||
namespace | namespace | |||
{ | { | |||
// External message node. | // Internal message node. | |||
class ExtMessageNode : public MessageNode | class IntMessageNode : public MessageNode | |||
{ | { | |||
public: | public: | |||
ExtMessageNode(thread_db* tdbb, MemoryPool& pool, CompilerScratch * csb, USHORT message, | IntMessageNode(thread_db* tdbb, MemoryPool& pool, CompilerScratch * csb, USHORT message, | |||
Array<NestConst<Parameter> >& aParameters, const Format* aFormat) | Array<NestConst<Parameter> >& aParameters, const Format* aFormat) | |||
: MessageNode(pool), | : MessageNode(pool), | |||
parameters(aParameters), | parameters(aParameters), | |||
format(aFormat), | format(aFormat) | |||
isSpecial(pool) | ||||
{ | { | |||
setup(tdbb, csb, message, format->fmt_count); | setup(tdbb, csb, message, format->fmt_count); | |||
} | } | |||
virtual USHORT setupDesc(thread_db* tdbb, CompilerScratch* csb, U SHORT index, | virtual USHORT setupDesc(thread_db* tdbb, CompilerScratch* csb, U SHORT index, | |||
dsc* desc, ItemInfo* itemInfo) | dsc* desc, ItemInfo* itemInfo) | |||
{ | { | |||
*desc = format->fmt_desc[index]; | *desc = format->fmt_desc[index]; | |||
if (index % 2 == 0 && index / 2u < parameters.getCount()) | if (index % 2 == 0 && index / 2u < parameters.getCount()) | |||
skipping to change at line 106 | skipping to change at line 105 | |||
itemInfo->field = namePair; | itemInfo->field = namePair; | |||
itemInfo->nullable = fieldInfo.nullable; | itemInfo->nullable = fieldInfo.nullable; | |||
itemInfo->fullDomain = true; | itemInfo->fullDomain = true; | |||
} | } | |||
itemInfo->name = param->prm_name; | itemInfo->name = param->prm_name; | |||
if (!param->prm_nullable) | if (!param->prm_nullable) | |||
itemInfo->nullable = false; | itemInfo->nullable = false; | |||
isSpecial.getBuffer(index / 2 + 1)[index / 2] = i | ||||
temInfo->isSpecial(); | ||||
} | } | |||
return type_alignments[desc->dsc_dtype]; | return type_alignments[desc->dsc_dtype]; | |||
} | } | |||
public: | ||||
Array<NestConst<Parameter> >& parameters; | ||||
const Format* format; | ||||
}; | ||||
// External message node. | ||||
class ExtMessageNode : public MessageNode | ||||
{ | ||||
public: | ||||
ExtMessageNode(thread_db* tdbb, MemoryPool& pool, CompilerScratch | ||||
* csb, USHORT message, const Format* aFormat) | ||||
: MessageNode(pool), | ||||
format(aFormat) | ||||
{ | ||||
setup(tdbb, csb, message, format->fmt_count); | ||||
} | ||||
virtual USHORT setupDesc(thread_db* tdbb, CompilerScratch* csb, U | ||||
SHORT index, | ||||
dsc* desc, ItemInfo* itemInfo) | ||||
{ | ||||
*desc = format->fmt_desc[index]; | ||||
return type_alignments[desc->dsc_dtype]; | ||||
} | ||||
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request , ExeState* exeState) const | virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request , ExeState* exeState) const | |||
{ | { | |||
if (request->req_operation == jrd_req::req_evaluate) | if (request->req_operation == jrd_req::req_evaluate) | |||
{ | { | |||
// Clear the message. This is important for exter nal routines. | // Clear the message. This is important for exter nal routines. | |||
UCHAR* msg = request->getImpure<UCHAR>(impureOffs et); | UCHAR* msg = request->getImpure<UCHAR>(impureOffs et); | |||
memset(msg, 0, format->fmt_length); | memset(msg, 0, format->fmt_length); | |||
} | } | |||
return MessageNode::execute(tdbb, request, exeState); | return MessageNode::execute(tdbb, request, exeState); | |||
} | } | |||
public: | public: | |||
Array<NestConst<Parameter> >& parameters; | ||||
const Format* format; | const Format* format; | |||
Array<bool> isSpecial; | ||||
}; | }; | |||
// Initialize output parameters with their domains default value or NULL. | // Initialize output parameters with their domains default value or NULL. | |||
// Kind of blr_init_variable, but for parameters. | // Kind of blr_init_variable, but for parameters. | |||
class ExtInitParameterNode : public TypedNode<StmtNode, StmtNode::TYPE_EX T_INIT_PARAMETER> | class InitParameterNode : public TypedNode<StmtNode, StmtNode::TYPE_EXT_I NIT_PARAMETER> | |||
{ | { | |||
public: | public: | |||
ExtInitParameterNode(thread_db* tdbb, MemoryPool& pool, CompilerS | InitParameterNode(thread_db* tdbb, MemoryPool& pool, CompilerScra | |||
cratch* csb, | tch* csb, | |||
ExtMessageNode* aMessage, USHORT aArgNumber) | Array<NestConst<Parameter> >& parameters, Message | |||
Node* aMessage, USHORT aArgNumber) | ||||
: TypedNode<StmtNode, StmtNode::TYPE_EXT_INIT_PARAMETER>( pool), | : TypedNode<StmtNode, StmtNode::TYPE_EXT_INIT_PARAMETER>( pool), | |||
message(aMessage), | message(aMessage), | |||
argNumber(aArgNumber) | argNumber(aArgNumber) | |||
{ | { | |||
Parameter* parameter = message->parameters[argNumber / 2] | Parameter* parameter = parameters[argNumber / 2]; | |||
; | defaultValueNode = NULL; | |||
if (parameter->prm_mechanism == prm_mech_type_of || | if (parameter->prm_mechanism != prm_mech_type_of && | |||
fb_utils::implicit_domain(parameter->prm_field_so | !fb_utils::implicit_domain(parameter->prm_field_s | |||
urce.c_str()) || | ource.c_str())) | |||
!parameter->prm_default_value) | ||||
{ | { | |||
defaultValueNode = NULL; | MetaNamePair namePair(parameter->prm_field_source | |||
, ""); | ||||
FieldInfo fieldInfo; | ||||
bool exist = csb->csb_map_field_info.get(namePair | ||||
, fieldInfo); | ||||
if (exist && fieldInfo.defaultValue) | ||||
defaultValueNode = CMP_clone_node(tdbb, c | ||||
sb, fieldInfo.defaultValue); | ||||
} | } | |||
else | ||||
defaultValueNode = CMP_clone_node(tdbb, csb, para | ||||
meter->prm_default_value); | ||||
} | } | |||
string internalPrint(NodePrinter& printer) const | string internalPrint(NodePrinter& printer) const | |||
{ | { | |||
StmtNode::internalPrint(printer); | StmtNode::internalPrint(printer); | |||
NODE_PRINT(printer, message); | NODE_PRINT(printer, message); | |||
NODE_PRINT(printer, argNumber); | NODE_PRINT(printer, argNumber); | |||
NODE_PRINT(printer, defaultValueNode); | NODE_PRINT(printer, defaultValueNode); | |||
return "ExtInitParameterNode"; | return "InitParameterNode"; | |||
} | } | |||
void genBlr(DsqlCompilerScratch* /*dsqlScratch*/) | void genBlr(DsqlCompilerScratch* /*dsqlScratch*/) | |||
{ | { | |||
} | } | |||
ExtInitParameterNode* pass1(thread_db* tdbb, CompilerScratch* csb ) | InitParameterNode* pass1(thread_db* tdbb, CompilerScratch* csb) | |||
{ | { | |||
doPass1(tdbb, csb, &defaultValueNode); | doPass1(tdbb, csb, &defaultValueNode); | |||
return this; | return this; | |||
} | } | |||
ExtInitParameterNode* pass2(thread_db* tdbb, CompilerScratch* csb ) | InitParameterNode* pass2(thread_db* tdbb, CompilerScratch* csb) | |||
{ | { | |||
ExprNode::doPass2(tdbb, csb, &defaultValueNode); | ExprNode::doPass2(tdbb, csb, &defaultValueNode); | |||
return this; | return this; | |||
} | } | |||
const StmtNode* execute(thread_db* tdbb, jrd_req* request, ExeSta te* /*exeState*/) const | const StmtNode* execute(thread_db* tdbb, jrd_req* request, ExeSta te* /*exeState*/) const | |||
{ | { | |||
if (request->req_operation == jrd_req::req_evaluate) | if (request->req_operation == jrd_req::req_evaluate) | |||
{ | { | |||
dsc* defaultDesc = NULL; | dsc* defaultDesc = NULL; | |||
skipping to change at line 226 | skipping to change at line 248 | |||
MOV_move(tdbb, &temp, &desc); | MOV_move(tdbb, &temp, &desc); | |||
} | } | |||
request->req_operation = jrd_req::req_return; | request->req_operation = jrd_req::req_return; | |||
} | } | |||
return parentStmt; | return parentStmt; | |||
} | } | |||
private: | private: | |||
ExtMessageNode* message; | MessageNode* message; | |||
USHORT argNumber; | USHORT argNumber; | |||
ValueExprNode* defaultValueNode; | ValueExprNode* defaultValueNode; | |||
}; | }; | |||
// External output parameters initialization. | // Output parameters initialization. | |||
class ExtInitOutputNode : public CompoundStmtNode | class InitOutputNode : public CompoundStmtNode | |||
{ | { | |||
public: | public: | |||
ExtInitOutputNode(thread_db* tdbb, MemoryPool& pool, CompilerScra | InitOutputNode(thread_db* tdbb, MemoryPool& pool, CompilerScratch | |||
tch* csb, | * csb, | |||
ExtMessageNode* message) | Array<NestConst<Parameter> >& parameters, Message | |||
Node* message) | ||||
: CompoundStmtNode(pool) | : CompoundStmtNode(pool) | |||
{ | { | |||
// Iterate over the format items, except the EOF item. | // Iterate over the format items, except the EOF item. | |||
for (USHORT i = 0; i < (message->format->fmt_count / 2) * 2; i += 2) | for (USHORT i = 0; i < (message->format->fmt_count / 2) * 2; i += 2) | |||
{ | { | |||
ExtInitParameterNode* init = FB_NEW_POOL(pool) Ex | InitParameterNode* init = FB_NEW_POOL(pool) InitP | |||
tInitParameterNode( | arameterNode( | |||
tdbb, pool, csb, message, i); | tdbb, pool, csb, parameters, message, i); | |||
statements.add(init); | statements.add(init); | |||
} | } | |||
} | } | |||
}; | }; | |||
// External parameters validation. | // Move parameters from a message to another, validating theirs values. | |||
class ExtValidationNode : public CompoundStmtNode | class MessageMoverNode : public CompoundStmtNode | |||
{ | { | |||
public: | public: | |||
ExtValidationNode(MemoryPool& pool, ExtMessageNode* message, bool procedure, bool input) | MessageMoverNode(MemoryPool& pool, MessageNode* fromMessage, Mess ageNode* toMessage) | |||
: CompoundStmtNode(pool) | : CompoundStmtNode(pool) | |||
{ | { | |||
// Iterate over the format items, except the EOF item. | // Iterate over the format items, except the EOF item. | |||
for (USHORT i = 0; i < (message->format->fmt_count / 2) * 2; i += 2) | for (USHORT i = 0; i < (fromMessage->format->fmt_count / 2) * 2; i += 2) | |||
{ | { | |||
if (!message->isSpecial[i / 2]) | ||||
continue; | ||||
ParameterNode* flag = FB_NEW_POOL(pool) Parameter Node(pool); | ParameterNode* flag = FB_NEW_POOL(pool) Parameter Node(pool); | |||
flag->message = message; | flag->message = fromMessage; | |||
flag->argNumber = i + 1; | flag->argNumber = i + 1; | |||
ParameterNode* param = FB_NEW_POOL(pool) Paramete rNode(pool); | ParameterNode* param = FB_NEW_POOL(pool) Paramete rNode(pool); | |||
param->message = message; | param->message = fromMessage; | |||
param->argNumber = i; | param->argNumber = i; | |||
param->argFlag = flag; | param->argFlag = flag; | |||
AssignmentNode* assign = FB_NEW_POOL(pool) Assign mentNode(pool); | AssignmentNode* assign = FB_NEW_POOL(pool) Assign mentNode(pool); | |||
assign->asgnFrom = param; | assign->asgnFrom = param; | |||
statements.add(assign); | statements.add(assign); | |||
// It's sufficient to assign input parameters to | flag = FB_NEW_POOL(pool) ParameterNode(pool); | |||
NULL, but output parameters | flag->message = toMessage; | |||
// need to be assigned to themselves to validate | flag->argNumber = i + 1; | |||
correctly. | ||||
if (input) | ||||
assign->asgnTo = FB_NEW_POOL(pool) NullNo | ||||
de(pool); | ||||
else | ||||
{ | ||||
flag = FB_NEW_POOL(pool) ParameterNode(po | ||||
ol); | ||||
flag->message = message; | ||||
flag->argNumber = i + 1; | ||||
param = FB_NEW_POOL(pool) ParameterNode(p | ||||
ool); | ||||
param->message = message; | ||||
param->argNumber = i; | ||||
param->argFlag = flag; | ||||
assign->asgnTo = param; | param = FB_NEW_POOL(pool) ParameterNode(pool); | |||
} | param->message = toMessage; | |||
} | param->argNumber = i; | |||
param->argFlag = flag; | ||||
// A stall is required to read req_proc_fetch state corre | assign->asgnTo = param; | |||
ctly. | } | |||
if (procedure) | ||||
statements.add(FB_NEW_POOL(pool) StallNode(pool)) | ||||
; | ||||
} | } | |||
}; | }; | |||
// External function node. | // External function node. | |||
class ExtFunctionNode : public SuspendNode | class ExtFunctionNode : public SuspendNode | |||
{ | { | |||
public: | public: | |||
ExtFunctionNode(MemoryPool& pool, const ReceiveNode* aReceiveNode , | ExtFunctionNode(MemoryPool& pool, const MessageNode* aExtInMessag eNode, const MessageNode* aExtOutMessageNode, | |||
const ExtEngineManager::Function* aFunction) | const ExtEngineManager::Function* aFunction) | |||
: SuspendNode(pool), | : SuspendNode(pool), | |||
receiveNode(aReceiveNode), | extInMessageNode(aExtInMessageNode), | |||
extOutMessageNode(aExtOutMessageNode), | ||||
function(aFunction) | function(aFunction) | |||
{ | { | |||
} | } | |||
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request , ExeState* exeState) const | virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request , ExeState* exeState) const | |||
{ | { | |||
if (request->req_operation == jrd_req::req_evaluate) | if (request->req_operation == jrd_req::req_evaluate) | |||
{ | { | |||
UCHAR* inMsg = receiveNode ? | UCHAR* inMsg = extInMessageNode ? request->getImp | |||
request->getImpure<UCHAR>(receiveNode->me | ure<UCHAR>(extInMessageNode->impureOffset) : NULL; | |||
ssage->impureOffset) : NULL; | UCHAR* outMsg = request->getImpure<UCHAR>(extOutM | |||
UCHAR* outMsg = request->getImpure<UCHAR>(message | essageNode->impureOffset); | |||
->impureOffset); | ||||
function->execute(tdbb, inMsg, outMsg); | function->execute(tdbb, inMsg, outMsg); | |||
} | } | |||
return SuspendNode::execute(tdbb, request, exeState); | return SuspendNode::execute(tdbb, request, exeState); | |||
} | } | |||
private: | private: | |||
const ReceiveNode* receiveNode; | const MessageNode* extInMessageNode; | |||
const MessageNode* extOutMessageNode; | ||||
const ExtEngineManager::Function* function; | const ExtEngineManager::Function* function; | |||
}; | }; | |||
// External procedure node. | // External procedure node. | |||
class ExtProcedureNode : public SuspendNode | class ExtProcedureNode : public CompoundStmtNode | |||
{ | { | |||
public: | public: | |||
ExtProcedureNode(MemoryPool& pool, const ReceiveNode* aReceiveNod | ExtProcedureNode(MemoryPool& pool, MessageNode* aExtInMessageNode | |||
e, | , MessageNode* aExtOutMessageNode, | |||
const ExtEngineManager::Procedure* aProcedure) | MessageNode* aIntOutMessageNode, const ExtEngineM | |||
: SuspendNode(pool), | anager::Procedure* aProcedure) | |||
receiveNode(aReceiveNode), | : CompoundStmtNode(pool), | |||
extInMessageNode(aExtInMessageNode), | ||||
extOutMessageNode(aExtOutMessageNode), | ||||
intOutMessageNode(aIntOutMessageNode), | ||||
procedure(aProcedure) | procedure(aProcedure) | |||
{ | { | |||
SuspendNode* suspend = FB_NEW_POOL(pool) SuspendNode(pool | ||||
); | ||||
suspend->message = intOutMessageNode; | ||||
suspend->statement = FB_NEW_POOL(getPool()) MessageMoverN | ||||
ode(pool, extOutMessageNode, intOutMessageNode); | ||||
statements.add(suspend); | ||||
statements.add(FB_NEW_POOL(getPool()) StallNode(pool)); | ||||
} | } | |||
virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request , ExeState* exeState) const | virtual const StmtNode* execute(thread_db* tdbb, jrd_req* request , ExeState* exeState) const | |||
{ | { | |||
impure_state* const impure = request->getImpure<impure_st ate>(impureOffset); | ||||
ExtEngineManager::ResultSet*& resultSet = request->req_ex t_resultset; | ExtEngineManager::ResultSet*& resultSet = request->req_ex t_resultset; | |||
UCHAR* inMsg = receiveNode ? | UCHAR* extInMsg = extInMessageNode ? request->getImpure<U | |||
request->getImpure<UCHAR>(receiveNode->message->i | CHAR>(extInMessageNode->impureOffset) : NULL; | |||
mpureOffset) : NULL; | UCHAR* extOutMsg = extOutMessageNode ? request->getImpure | |||
UCHAR* outMsg = request->getImpure<UCHAR>(message->impure | <UCHAR>(extOutMessageNode->impureOffset) : NULL; | |||
Offset); | UCHAR* intOutMsg = intOutMessageNode ? request->getImpure | |||
USHORT* eof = (USHORT*) (outMsg + (IPTR) message->format- | <UCHAR>(intOutMessageNode->impureOffset) : NULL; | |||
>fmt_desc.back().dsc_address); | SSHORT* eof = intOutMsg ? | |||
(SSHORT*) (intOutMsg + (IPTR) intOutMessageNode-> | ||||
format->fmt_desc.back().dsc_address) : NULL; | ||||
switch (request->req_operation) | switch (request->req_operation) | |||
{ | { | |||
case jrd_req::req_evaluate: | case jrd_req::req_evaluate: | |||
fb_assert(!resultSet && *eof == 0); | fb_assert(!resultSet); | |||
resultSet = procedure->open(tdbb, inMsg, | resultSet = procedure->open(tdbb, extInMs | |||
outMsg); | g, extOutMsg); | |||
if (resultSet) | if (!resultSet) | |||
*eof = -1; | ||||
else | ||||
{ | { | |||
if (!(request->req_flags & req_pr | *eof = 0; | |||
oc_fetch)) | break; | |||
{ | ||||
request->req_operation = | ||||
jrd_req::req_evaluate; | ||||
return statement; | ||||
} | ||||
} | } | |||
else | ||||
request->req_operation = jrd_req::req_ret | *eof = -1; | |||
urn; | ||||
// fall into | // fall into | |||
case jrd_req::req_return: | case jrd_req::req_proceed: | |||
if (*eof == 0) | case jrd_req::req_sync: | |||
{ | if (resultSet) | |||
fb_assert(!resultSet); | ||||
return parentStmt; | ||||
} | ||||
fb_assert(resultSet); | ||||
if (!resultSet->fetch(tdbb) || !(request- | ||||
>req_flags & req_proc_fetch)) | ||||
{ | { | |||
*eof = 0; | if (resultSet->fetch(tdbb) && (re | |||
delete resultSet; | quest->req_flags & req_proc_fetch)) | |||
resultSet = NULL; | *eof = -1; | |||
else | ||||
{ | ||||
*eof = 0; | ||||
delete resultSet; | ||||
resultSet = NULL; | ||||
} | ||||
} | } | |||
impure->sta_state = 0; // suspend node | ||||
request->req_operation = jrd_req::req_syn | ||||
c; | ||||
break; | break; | |||
case jrd_req::req_proceed: | ||||
request->req_operation = jrd_req::req_eva | ||||
luate; | ||||
return statement; | ||||
case jrd_req::req_unwind: | case jrd_req::req_unwind: | |||
delete resultSet; | delete resultSet; | |||
resultSet = NULL; | resultSet = NULL; | |||
break; | break; | |||
} | } | |||
return SuspendNode::execute(tdbb, request, exeState); | return CompoundStmtNode::execute(tdbb, request, exeState) ; | |||
} | } | |||
private: | private: | |||
const ReceiveNode* receiveNode; | MessageNode* extInMessageNode; | |||
MessageNode* extOutMessageNode; | ||||
MessageNode* intOutMessageNode; | ||||
const ExtEngineManager::Procedure* procedure; | const ExtEngineManager::Procedure* procedure; | |||
}; | }; | |||
// External trigger node. | // External trigger node. | |||
class ExtTriggerNode : public TypedNode<StmtNode, StmtNode::TYPE_EXT_TRIG GER> | class ExtTriggerNode : public TypedNode<StmtNode, StmtNode::TYPE_EXT_TRIG GER> | |||
{ | { | |||
public: | public: | |||
ExtTriggerNode(MemoryPool& pool, const ExtEngineManager::Trigger* aTrigger) | ExtTriggerNode(MemoryPool& pool, const ExtEngineManager::Trigger* aTrigger) | |||
: TypedNode<StmtNode, StmtNode::TYPE_EXT_TRIGGER>(pool), | : TypedNode<StmtNode, StmtNode::TYPE_EXT_TRIGGER>(pool), | |||
trigger(aTrigger) | trigger(aTrigger) | |||
skipping to change at line 588 | skipping to change at line 600 | |||
externalAttachment(NULL), | externalAttachment(NULL), | |||
externalTransaction(NULL), | externalTransaction(NULL), | |||
miscInfo(*internalAttachment->att_pool) | miscInfo(*internalAttachment->att_pool) | |||
{ | { | |||
//// TODO: admin rights | //// TODO: admin rights | |||
clientCharSet = INTL_charset_lookup(tdbb, internalAttachment->att_client_ charset)->getName(); | clientCharSet = INTL_charset_lookup(tdbb, internalAttachment->att_client_ charset)->getName(); | |||
internalAttachment->getStable()->addRef(); | internalAttachment->getStable()->addRef(); | |||
externalAttachment = MasterInterfacePtr()->registerAttachment(JProvider:: | externalAttachment = MasterInterfacePtr()->registerAttachment | |||
getInstance(), | (AutoPlugin<JProvider>(JProvider::getInstance()), internalAttachm | |||
internalAttachment->getInterface()); | ent->getInterface()); | |||
} | } | |||
ExtEngineManager::ExternalContextImpl::~ExternalContextImpl() | ExtEngineManager::ExternalContextImpl::~ExternalContextImpl() | |||
{ | { | |||
releaseTransaction(); | releaseTransaction(); | |||
if (externalAttachment) | if (externalAttachment) | |||
{ | { | |||
externalAttachment->release(); | externalAttachment->release(); | |||
externalAttachment = NULL; | externalAttachment = NULL; | |||
skipping to change at line 616 | skipping to change at line 628 | |||
{ | { | |||
externalTransaction->release(); | externalTransaction->release(); | |||
externalTransaction = NULL; | externalTransaction = NULL; | |||
} | } | |||
internalTransaction = NULL; | internalTransaction = NULL; | |||
} | } | |||
void ExtEngineManager::ExternalContextImpl::setTransaction(thread_db* tdbb) | void ExtEngineManager::ExternalContextImpl::setTransaction(thread_db* tdbb) | |||
{ | { | |||
jrd_tra* newTransaction = tdbb->getTransaction(); | ITransaction* newTransaction = tdbb->getTransaction() ? tdbb->getTransact ion()->getInterface(true) : NULL; | |||
if (newTransaction == internalTransaction) | if (newTransaction == internalTransaction) | |||
return; | return; | |||
releaseTransaction(); | releaseTransaction(); | |||
fb_assert(!externalTransaction); | fb_assert(!externalTransaction && !internalTransaction); | |||
if ((internalTransaction = newTransaction)) | if ((internalTransaction = newTransaction)) | |||
{ | externalTransaction = MasterInterfacePtr()->registerTransaction(e | |||
internalTransaction->getInterface()->addRef(); | xternalAttachment, internalTransaction); | |||
externalTransaction = MasterInterfacePtr()->registerTransaction(e | ||||
xternalAttachment, | ||||
internalTransaction->getInterface()); | ||||
} | ||||
} | } | |||
IMaster* ExtEngineManager::ExternalContextImpl::getMaster() | IMaster* ExtEngineManager::ExternalContextImpl::getMaster() | |||
{ | { | |||
MasterInterfacePtr master; | MasterInterfacePtr master; | |||
return master; | return master; | |||
} | } | |||
IExternalEngine* ExtEngineManager::ExternalContextImpl::getEngine(CheckStatusWra pper* /*status*/) | IExternalEngine* ExtEngineManager::ExternalContextImpl::getEngine(CheckStatusWra pper* /*status*/) | |||
{ | { | |||
skipping to change at line 1047 | skipping to change at line 1054 | |||
FbLocalStatus status; | FbLocalStatus status; | |||
RefPtr<IMetadataBuilder> inBuilder(REF_NO_INCR, metadata->inputParameters ->getBuilder(&status)); | RefPtr<IMetadataBuilder> inBuilder(REF_NO_INCR, metadata->inputParameters ->getBuilder(&status)); | |||
status.check(); | status.check(); | |||
RefPtr<IMetadataBuilder> outBuilder(REF_NO_INCR, metadata->outputParamete rs->getBuilder(&status)); | RefPtr<IMetadataBuilder> outBuilder(REF_NO_INCR, metadata->outputParamete rs->getBuilder(&status)); | |||
status.check(); | status.check(); | |||
IExternalFunction* externalFunction; | IExternalFunction* externalFunction; | |||
RefPtr<IMessageMetadata> extInputParameters, extOutputParameters; | ||||
{ // scope | { // scope | |||
EngineCheckout cout(tdbb, FB_FUNCTION); | EngineCheckout cout(tdbb, FB_FUNCTION); | |||
externalFunction = attInfo->engine->makeFunction(&status, attInfo ->context, metadata, | externalFunction = attInfo->engine->makeFunction(&status, attInfo ->context, metadata, | |||
inBuilder, outBuilder); | inBuilder, outBuilder); | |||
status.check(); | status.check(); | |||
if (!externalFunction) | if (!externalFunction) | |||
{ | { | |||
status_exception::raise( | status_exception::raise( | |||
Arg::Gds(isc_eem_func_not_returned) << udf->getNa me().toString() << engine); | Arg::Gds(isc_eem_func_not_returned) << udf->getNa me().toString() << engine); | |||
} | } | |||
metadata->inputParameters = inBuilder->getMetadata(&status); | extInputParameters = inBuilder->getMetadata(&status); | |||
status.check(); | status.check(); | |||
metadata->outputParameters = outBuilder->getMetadata(&status); | extOutputParameters = outBuilder->getMetadata(&status); | |||
status.check(); | status.check(); | |||
} | } | |||
udf->setInputFormat(Routine::createFormat(pool, metadata->inputParameters , false)); | udf->setInputFormat(Routine::createFormat(pool, metadata->inputParameters , false)); | |||
udf->setOutputFormat(Routine::createFormat(pool, metadata->outputParamete rs, true)); | udf->setOutputFormat(Routine::createFormat(pool, metadata->outputParamete rs, true)); | |||
const Format* extInputFormat = Routine::createFormat(pool, extInputParame | ||||
ters, false); | ||||
const Format* extOutputFormat = Routine::createFormat(pool, extOutputPara | ||||
meters, true); | ||||
try | try | |||
{ | { | |||
udf->fun_external = FB_NEW_POOL(getPool()) Function(tdbb, this, a ttInfo->engine, | udf->fun_external = FB_NEW_POOL(getPool()) Function(tdbb, this, a ttInfo->engine, | |||
metadata.release(), externalFunction, udf); | metadata.release(), externalFunction, udf); | |||
CompoundStmtNode* mainNode = FB_NEW_POOL(getPool()) CompoundStmtN ode(getPool()); | CompoundStmtNode* mainNode = FB_NEW_POOL(getPool()) CompoundStmtN ode(getPool()); | |||
ExtMessageNode* inMessageNode = udf->getInputFields().hasData() ? | IntMessageNode* intInMessageNode = udf->getInputFields().hasData( | |||
FB_NEW_POOL(getPool()) ExtMessageNode(tdbb, getPool(), cs | ) ? | |||
b, 0, | FB_NEW_POOL(getPool()) IntMessageNode(tdbb, getPool(), cs | |||
b, 0, | ||||
udf->getInputFields(), udf->getInputFormat()) : | udf->getInputFields(), udf->getInputFormat()) : | |||
NULL; | NULL; | |||
if (inMessageNode) | ExtMessageNode* extInMessageNode = NULL; | |||
mainNode->statements.add(inMessageNode); | ||||
if (intInMessageNode) | ||||
{ | ||||
mainNode->statements.add(intInMessageNode); | ||||
extInMessageNode = FB_NEW_POOL(getPool()) ExtMessageNode( | ||||
tdbb, getPool(), csb, 2, extInputFormat); | ||||
mainNode->statements.add(extInMessageNode); | ||||
} | ||||
ExtMessageNode* outMessageNode = FB_NEW_POOL(getPool()) ExtMessag eNode(tdbb, getPool(), csb, 1, | IntMessageNode* intOutMessageNode = FB_NEW_POOL(getPool()) IntMes sageNode(tdbb, getPool(), csb, 1, | |||
udf->getOutputFields(), udf->getOutputFormat()); | udf->getOutputFields(), udf->getOutputFormat()); | |||
mainNode->statements.add(outMessageNode); | mainNode->statements.add(intOutMessageNode); | |||
ExtInitOutputNode* initOutputNode = FB_NEW_POOL(getPool()) ExtIni | ExtMessageNode* extOutMessageNode = FB_NEW_POOL(getPool()) ExtMes | |||
tOutputNode( | sageNode(tdbb, getPool(), csb, 3, | |||
tdbb, getPool(), csb, outMessageNode); | extOutputFormat); | |||
mainNode->statements.add(extOutMessageNode); | ||||
// Initialize the output fields into the external message. | ||||
InitOutputNode* initOutputNode = FB_NEW_POOL(getPool()) InitOutpu | ||||
tNode( | ||||
tdbb, getPool(), csb, udf->getOutputFields(), extOutMessa | ||||
geNode); | ||||
mainNode->statements.add(initOutputNode); | mainNode->statements.add(initOutputNode); | |||
ReceiveNode* receiveNode = inMessageNode ? | if (intInMessageNode) | |||
FB_NEW_POOL(getPool()) ReceiveNode(getPool()) : NULL; | ||||
if (inMessageNode) | ||||
{ | { | |||
receiveNode->message = inMessageNode; | ReceiveNode* receiveNode = intInMessageNode ? FB_NEW_POOL | |||
receiveNode->statement = FB_NEW_POOL(getPool()) ExtValida | (getPool()) ReceiveNode(getPool()) : NULL; | |||
tionNode( | receiveNode->message = intInMessageNode; | |||
getPool(), inMessageNode, false, true); | receiveNode->statement = FB_NEW_POOL(getPool()) MessageMo | |||
verNode( | ||||
getPool(), intInMessageNode, extInMessageNode); | ||||
mainNode->statements.add(receiveNode); | mainNode->statements.add(receiveNode); | |||
} | } | |||
ExtFunctionNode* extFunctionNode = FB_NEW_POOL(getPool()) ExtFunc tionNode(getPool(), | ExtFunctionNode* extFunctionNode = FB_NEW_POOL(getPool()) ExtFunc tionNode(getPool(), | |||
receiveNode, udf->fun_external); | extInMessageNode, extOutMessageNode, udf->fun_external); | |||
mainNode->statements.add(extFunctionNode); | mainNode->statements.add(extFunctionNode); | |||
extFunctionNode->message = outMessageNode; | extFunctionNode->message = intOutMessageNode; | |||
extFunctionNode->statement = FB_NEW_POOL(getPool()) ExtValidation | extFunctionNode->statement = FB_NEW_POOL(getPool()) MessageMoverN | |||
Node( | ode( | |||
getPool(), outMessageNode, false, false); | getPool(), extOutMessageNode, intOutMessageNode); | |||
JrdStatement* statement = udf->getStatement(); | JrdStatement* statement = udf->getStatement(); | |||
PAR_preparsed_node(tdbb, NULL, mainNode, NULL, &csb, &statement, false, 0); | PAR_preparsed_node(tdbb, NULL, mainNode, NULL, &csb, &statement, false, 0); | |||
udf->setStatement(statement); | udf->setStatement(statement); | |||
} | } | |||
catch (...) | catch (...) | |||
{ | { | |||
EngineCheckout cout(tdbb, FB_FUNCTION); | EngineCheckout cout(tdbb, FB_FUNCTION); | |||
externalFunction->dispose(); | externalFunction->dispose(); | |||
throw; | throw; | |||
skipping to change at line 1155 | skipping to change at line 1176 | |||
FbLocalStatus status; | FbLocalStatus status; | |||
RefPtr<IMetadataBuilder> inBuilder(REF_NO_INCR, metadata->inputParameters ->getBuilder(&status)); | RefPtr<IMetadataBuilder> inBuilder(REF_NO_INCR, metadata->inputParameters ->getBuilder(&status)); | |||
status.check(); | status.check(); | |||
RefPtr<IMetadataBuilder> outBuilder(REF_NO_INCR, metadata->outputParamete rs->getBuilder(&status)); | RefPtr<IMetadataBuilder> outBuilder(REF_NO_INCR, metadata->outputParamete rs->getBuilder(&status)); | |||
status.check(); | status.check(); | |||
IExternalProcedure* externalProcedure; | IExternalProcedure* externalProcedure; | |||
RefPtr<IMessageMetadata> extInputParameters, extOutputParameters; | ||||
{ // scope | { // scope | |||
EngineCheckout cout(tdbb, FB_FUNCTION); | EngineCheckout cout(tdbb, FB_FUNCTION); | |||
externalProcedure = attInfo->engine->makeProcedure(&status, attIn fo->context, metadata, | externalProcedure = attInfo->engine->makeProcedure(&status, attIn fo->context, metadata, | |||
inBuilder, outBuilder); | inBuilder, outBuilder); | |||
status.check(); | status.check(); | |||
if (!externalProcedure) | if (!externalProcedure) | |||
{ | { | |||
status_exception::raise( | status_exception::raise( | |||
Arg::Gds(isc_eem_proc_not_returned) << | Arg::Gds(isc_eem_proc_not_returned) << | |||
prc->getName().toString() << engine); | prc->getName().toString() << engine); | |||
} | } | |||
metadata->inputParameters = inBuilder->getMetadata(&status); | extInputParameters = inBuilder->getMetadata(&status); | |||
status.check(); | status.check(); | |||
metadata->outputParameters = outBuilder->getMetadata(&status); | extOutputParameters = outBuilder->getMetadata(&status); | |||
status.check(); | status.check(); | |||
} | } | |||
prc->setInputFormat(Routine::createFormat(pool, metadata->inputParameters , false)); | prc->setInputFormat(Routine::createFormat(pool, metadata->inputParameters , false)); | |||
prc->setOutputFormat(Routine::createFormat(pool, metadata->outputParamete rs, true)); | prc->setOutputFormat(Routine::createFormat(pool, metadata->outputParamete rs, true)); | |||
const Format* extInputFormat = Routine::createFormat(pool, extInputParame | ||||
ters, false); | ||||
const Format* extOutputFormat = Routine::createFormat(pool, extOutputPara | ||||
meters, true); | ||||
try | try | |||
{ | { | |||
prc->setExternal(FB_NEW_POOL(getPool()) Procedure(tdbb, this, att Info->engine, | prc->setExternal(FB_NEW_POOL(getPool()) Procedure(tdbb, this, att Info->engine, | |||
metadata.release(), externalProcedure, prc)); | metadata.release(), externalProcedure, prc)); | |||
CompoundStmtNode* mainNode = FB_NEW_POOL(getPool()) CompoundStmtN ode(getPool()); | CompoundStmtNode* mainNode = FB_NEW_POOL(getPool()) CompoundStmtN ode(getPool()); | |||
ExtMessageNode* inMessageNode = prc->getInputFields().hasData() ? | IntMessageNode* intInMessageNode = prc->getInputFields().hasData( | |||
FB_NEW_POOL(getPool()) ExtMessageNode(tdbb, getPool(), cs | ) ? | |||
b, 0, | FB_NEW_POOL(getPool()) IntMessageNode(tdbb, getPool(), cs | |||
b, 0, | ||||
prc->getInputFields(), prc->getInputFormat()) : | prc->getInputFields(), prc->getInputFormat()) : | |||
NULL; | NULL; | |||
if (inMessageNode) | ExtMessageNode* extInMessageNode = NULL; | |||
mainNode->statements.add(inMessageNode); | ||||
if (intInMessageNode) | ||||
{ | ||||
mainNode->statements.add(intInMessageNode); | ||||
ExtMessageNode* outMessageNode = FB_NEW_POOL(getPool()) ExtMessag | extInMessageNode = FB_NEW_POOL(getPool()) ExtMessageNode( | |||
eNode(tdbb, getPool(), csb, 1, | tdbb, getPool(), csb, 2, extInputFormat); | |||
mainNode->statements.add(extInMessageNode); | ||||
} | ||||
IntMessageNode* intOutMessageNode = FB_NEW_POOL(getPool()) IntMes | ||||
sageNode(tdbb, getPool(), csb, 1, | ||||
prc->getOutputFields(), prc->getOutputFormat()); | prc->getOutputFields(), prc->getOutputFormat()); | |||
mainNode->statements.add(outMessageNode); | mainNode->statements.add(intOutMessageNode); | |||
ExtInitOutputNode* initOutputNode = FB_NEW_POOL(getPool()) ExtIni | ExtMessageNode* extOutMessageNode = FB_NEW_POOL(getPool()) ExtMes | |||
tOutputNode( | sageNode(tdbb, getPool(), | |||
tdbb, getPool(), csb, outMessageNode); | csb, 3, extOutputFormat); | |||
mainNode->statements.add(extOutMessageNode); | ||||
// Initialize the output fields into the external message. | ||||
InitOutputNode* initOutputNode = FB_NEW_POOL(getPool()) InitOutpu | ||||
tNode( | ||||
tdbb, getPool(), csb, prc->getOutputFields(), extOutMessa | ||||
geNode); | ||||
mainNode->statements.add(initOutputNode); | mainNode->statements.add(initOutputNode); | |||
ReceiveNode* receiveNode = inMessageNode ? | ReceiveNode* receiveNode = intInMessageNode ? | |||
FB_NEW_POOL(getPool()) ReceiveNode(getPool()) : NULL; | FB_NEW_POOL(getPool()) ReceiveNode(getPool()) : NULL; | |||
if (inMessageNode) | if (intInMessageNode) | |||
{ | { | |||
receiveNode->message = inMessageNode; | CompoundStmtNode* receiveSubStatement = FB_NEW_POOL(getPo | |||
receiveNode->statement = FB_NEW_POOL(getPool()) ExtValida | ol()) CompoundStmtNode(getPool()); | |||
tionNode( | receiveSubStatement->statements.add(FB_NEW_POOL(getPool() | |||
getPool(), inMessageNode, true, true); | ) MessageMoverNode( | |||
getPool(), intInMessageNode, extInMessageNode)); | ||||
receiveSubStatement->statements.add(FB_NEW_POOL(getPool() | ||||
) StallNode(getPool())); | ||||
receiveNode->statement = receiveSubStatement; | ||||
receiveNode->message = intInMessageNode; | ||||
mainNode->statements.add(receiveNode); | mainNode->statements.add(receiveNode); | |||
} | } | |||
else | ||||
mainNode->statements.add(FB_NEW_POOL(getPool()) StallNode | ||||
(getPool())); | ||||
ExtProcedureNode* extProcedureNode = FB_NEW_POOL(getPool()) ExtPr ocedureNode(getPool(), | ExtProcedureNode* extProcedureNode = FB_NEW_POOL(getPool()) ExtPr ocedureNode(getPool(), | |||
receiveNode, prc->getExternal()); | extInMessageNode, extOutMessageNode, intOutMessageNode, p rc->getExternal()); | |||
mainNode->statements.add(extProcedureNode); | mainNode->statements.add(extProcedureNode); | |||
extProcedureNode->message = outMessageNode; | ||||
extProcedureNode->statement = FB_NEW_POOL(getPool()) ExtValidatio | ||||
nNode( | ||||
getPool(), outMessageNode, true, false); | ||||
JrdStatement* statement = prc->getStatement(); | JrdStatement* statement = prc->getStatement(); | |||
PAR_preparsed_node(tdbb, NULL, mainNode, NULL, &csb, &statement, false, 0); | PAR_preparsed_node(tdbb, NULL, mainNode, NULL, &csb, &statement, false, 0); | |||
prc->setStatement(statement); | prc->setStatement(statement); | |||
} | } | |||
catch (...) | catch (...) | |||
{ | { | |||
EngineCheckout cout(tdbb, FB_FUNCTION); | EngineCheckout cout(tdbb, FB_FUNCTION); | |||
externalProcedure->dispose(); | externalProcedure->dispose(); | |||
throw; | throw; | |||
End of changes. 80 change blocks. | ||||
191 lines changed or deleted | 245 lines changed or added |