|
From: <asf...@us...> - 2013-03-04 01:43:01
|
Revision: 57719
http://sourceforge.net/p/firebird/code/57719
Author: asfernandes
Date: 2013-03-04 01:42:58 +0000 (Mon, 04 Mar 2013)
Log Message:
-----------
Fixing FB_MESSAGE macro and external functions and procedures.
Isolate external routines them from request-based ones.
Modified Paths:
--------------
firebird/trunk/examples/udr/UdrCppExample.cpp
firebird/trunk/src/dsql/ExprNodes.cpp
firebird/trunk/src/dsql/StmtNodes.cpp
firebird/trunk/src/include/firebird/ExternalEngine.h
firebird/trunk/src/include/firebird/Message.h
firebird/trunk/src/include/firebird/UdrCppEngine.h
firebird/trunk/src/include/firebird/UdrEngine.h
firebird/trunk/src/jrd/ExtEngineManager.cpp
firebird/trunk/src/jrd/ExtEngineManager.h
firebird/trunk/src/jrd/Function.epp
firebird/trunk/src/jrd/cmp.cpp
firebird/trunk/src/jrd/dfw.epp
firebird/trunk/src/jrd/exe.cpp
firebird/trunk/src/jrd/exe.h
firebird/trunk/src/jrd/jrd.h
firebird/trunk/src/jrd/met.epp
firebird/trunk/src/jrd/met_proto.h
firebird/trunk/src/jrd/recsrc/ProcedureScan.cpp
firebird/trunk/src/jrd/recsrc/RecordSource.h
firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp
Modified: firebird/trunk/examples/udr/UdrCppExample.cpp
===================================================================
--- firebird/trunk/examples/udr/UdrCppExample.cpp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/examples/udr/UdrCppExample.cpp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -117,451 +117,6 @@
//------------------------------------------------------------------------------
-class MessageImpl;
-
-class ParamDescBase
-{
-public:
- ParamDescBase()
- : pos(0),
- nullPos(0)
- {
- }
-
- unsigned pos;
- unsigned nullPos;
-};
-
-template <class T>
-class ParamDesc : public ParamDescBase
-{
-};
-
-template <>
-class ParamDesc<void*> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message, const Firebird::IParametersMetadata* aParams);
-
- unsigned align(unsigned size, unsigned aIndex)
- {
- index = aIndex;
-
- AutoDispose<IStatus> status(master->getStatus());
-
- switch ((type = params->getType(status, index)))
- {
- case SQL_SHORT:
- size = FB_ALIGN(size, sizeof(ISC_SHORT));
- break;
-
- case SQL_LONG:
- size = FB_ALIGN(size, sizeof(ISC_LONG));
- break;
-
- case SQL_INT64:
- size = FB_ALIGN(size, sizeof(ISC_INT64));
- break;
-
- case SQL_FLOAT:
- size = FB_ALIGN(size, sizeof(float));
- break;
-
- case SQL_DOUBLE:
- size = FB_ALIGN(size, sizeof(double));
- break;
-
- case SQL_BLOB:
- size = FB_ALIGN(size, sizeof(ISC_QUAD));
- break;
-
- case SQL_TEXT:
- case SQL_VARYING:
- size = FB_ALIGN(size, sizeof(ISC_USHORT));
- break;
-
- default:
- assert(false);
- break;
- }
-
- return size;
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- AutoDispose<IStatus> status(master->getStatus());
- unsigned ret;
-
- switch (type)
- {
- case SQL_SHORT:
- {
- unsigned scale = params->getScale(status, index);
- *blr++ = blr_short;
- *blr++ = scale;
- ret = sizeof(ISC_SHORT);
- break;
- }
-
- case SQL_LONG:
- {
- unsigned scale = params->getScale(status, index);
- *blr++ = blr_long;
- *blr++ = scale;
- ret = sizeof(ISC_LONG);
- break;
- }
-
- case SQL_INT64:
- {
- unsigned scale = params->getScale(status, index);
- *blr++ = blr_int64;
- *blr++ = scale;
- ret = sizeof(ISC_INT64);
- break;
- }
-
- case SQL_FLOAT:
- *blr++ = blr_float;
- ret = sizeof(float);
- break;
-
- case SQL_DOUBLE:
- *blr++ = blr_double;
- ret = sizeof(double);
- break;
-
- case SQL_BLOB:
- *blr++ = blr_blob2;
- *blr++ = 0;
- *blr++ = 0;
- *blr++ = 0;
- *blr++ = 0;
- ret = sizeof(ISC_QUAD);
- break;
-
- case SQL_TEXT:
- case SQL_VARYING:
- {
- unsigned length = params->getLength(status, index);
- *blr++ = blr_varying;
- *blr++ = length & 0xFF;
- *blr++ = (length >> 8) & 0xFF;
- ret = sizeof(ISC_USHORT) + length;
- break;
- }
-
- default:
- assert(false);
- ret = 0;
- break;
- }
-
- return ret;
- }
-
- unsigned getType() const
- {
- return type;
- }
-
-private:
- const Firebird::IParametersMetadata* params;
- unsigned type;
- unsigned index;
-};
-
-class MessageImpl : public Firebird::FbMessage
-{
-public:
- MessageImpl(unsigned aItemCount, void* aBuffer = NULL)
- : itemCount(aItemCount * 2),
- freeBuffer(!aBuffer),
- items(0)
- {
- static const ISC_UCHAR HEADER[] = {
- blr_version5,
- blr_begin,
- blr_message, 0, 0, 0
- };
-
- blrLength = 0;
- blr = blrPos = new ISC_UCHAR[sizeof(HEADER) + 10 * itemCount + 2];
- bufferLength = 0;
- buffer = static_cast<ISC_UCHAR*>(aBuffer);
-
- memcpy(blrPos, HEADER, sizeof(HEADER));
- blrPos += sizeof(HEADER);
- }
-
- ~MessageImpl()
- {
- if (freeBuffer && buffer)
- delete [] buffer;
-
- if (blr)
- delete [] blr;
- }
-
- template <typename T>
- void add(ParamDesc<T>& paramDesc)
- {
- if (items >= itemCount)
- return; // return an error, this is already constructed message
-
- bufferLength = paramDesc.align(bufferLength, items / 2);
- paramDesc.pos = bufferLength;
- bufferLength += paramDesc.addBlr(blrPos);
-
- bufferLength = FB_ALIGN(bufferLength, sizeof(ISC_SHORT));
- paramDesc.nullPos = bufferLength;
- bufferLength += sizeof(ISC_SHORT);
-
- *blrPos++ = blr_short;
- *blrPos++ = 0;
-
- items += 2;
-
- if (items == itemCount)
- {
- *blrPos++ = blr_end;
- *blrPos++ = blr_eoc;
-
- blrLength = blrPos - blr;
-
- ISC_UCHAR* blrStart = blrPos - blrLength;
- blrStart[4] = items & 0xFF;
- blrStart[5] = (items >> 8) & 0xFF;
-
- if (!buffer)
- {
- buffer = new ISC_UCHAR[bufferLength];
- memset(buffer, 0, bufferLength);
- }
- }
- }
-
- bool isNull(const ParamDescBase& index)
- {
- return *(ISC_SHORT*) (buffer + index.nullPos);
- }
-
- void setNull(const ParamDescBase& index, bool null)
- {
- *(ISC_SHORT*) (buffer + index.nullPos) = (ISC_SHORT) null;
- }
-
- template <typename T> T& operator [](const ParamDesc<T>& index)
- {
- return *(T*) (buffer + index.pos);
- }
-
- void* operator [](const ParamDesc<void*>& index)
- {
- return buffer + index.pos;
- }
-
-public:
- unsigned itemCount;
- bool freeBuffer;
- unsigned items;
- ISC_UCHAR* blrPos;
-};
-
-template <>
-class ParamDesc<ISC_SHORT> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message, ISC_UCHAR aScale = 0)
- : scale(aScale)
- {
- message.add(*this);
- }
-
- unsigned align(unsigned size, unsigned /*index*/)
- {
- return FB_ALIGN(size, sizeof(ISC_SHORT));
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- *blr++ = blr_short;
- *blr++ = scale;
- return sizeof(ISC_SHORT);
- }
-
-private:
- ISC_UCHAR scale;
-};
-
-template <>
-class ParamDesc<ISC_LONG> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message, ISC_UCHAR aScale = 0)
- : scale(aScale)
- {
- message.add(*this);
- }
-
- unsigned align(unsigned size, unsigned /*index*/)
- {
- return FB_ALIGN(size, sizeof(ISC_LONG));
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- *blr++ = blr_long;
- *blr++ = scale;
- return sizeof(ISC_LONG);
- }
-
-private:
- ISC_UCHAR scale;
-};
-
-template <>
-class ParamDesc<ISC_INT64> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message, ISC_UCHAR aScale = 0)
- : scale(aScale)
- {
- message.add(*this);
- }
-
- unsigned align(unsigned size, unsigned /*index*/)
- {
- return FB_ALIGN(size, sizeof(ISC_INT64));
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- *blr++ = blr_int64;
- *blr++ = scale;
- return sizeof(ISC_INT64);
- }
-
-private:
- ISC_UCHAR scale;
-};
-
-template <>
-class ParamDesc<float> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message)
- {
- message.add(*this);
- }
-
- unsigned align(unsigned size, unsigned /*index*/)
- {
- return FB_ALIGN(size, sizeof(float));
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- *blr++ = blr_float;
- return sizeof(float);
- }
-};
-
-template <>
-class ParamDesc<double> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message)
- {
- message.add(*this);
- }
-
- unsigned align(unsigned size, unsigned /*index*/)
- {
- return FB_ALIGN(size, sizeof(double));
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- *blr++ = blr_double;
- return sizeof(double);
- }
-};
-
-template <>
-class ParamDesc<ISC_QUAD> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message)
- {
- message.add(*this);
- }
-
- unsigned align(unsigned size, unsigned /*index*/)
- {
- return FB_ALIGN(size, sizeof(ISC_QUAD));
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- *blr++ = blr_blob2;
- *blr++ = 0;
- *blr++ = 0;
- *blr++ = 0;
- *blr++ = 0;
- return sizeof(ISC_QUAD);
- }
-};
-
-struct FbString
-{
- ISC_USHORT length;
- char str[1];
-};
-
-template <>
-class ParamDesc<FbString> : public ParamDescBase
-{
-public:
- ParamDesc(MessageImpl& message, ISC_USHORT aLength)
- : length(aLength)
- {
- message.add(*this);
- }
-
- unsigned align(unsigned size, unsigned /*index*/)
- {
- return FB_ALIGN(size, sizeof(ISC_USHORT));
- }
-
- unsigned addBlr(ISC_UCHAR*& blr)
- {
- *blr++ = blr_varying;
- *blr++ = length & 0xFF;
- *blr++ = (length >> 8) & 0xFF;
- return sizeof(ISC_USHORT) + length;
- }
-
-private:
- ISC_USHORT length;
-};
-
-//// TODO: boolean, date, time, timestamp
-
-//--------------------------------------
-
-inline ParamDesc<void*>::ParamDesc(MessageImpl& message, const Firebird::IParametersMetadata* aParams)
- : params(aParams),
- type(0)
-{
- message.add(*this);
-}
-
-
-//------------------------------------------------------------------------------
-
-
/***
create function wait_event (
event_name varchar(31) character set utf8 not null
@@ -614,37 +169,65 @@
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(sum_args)
+ // This function requires the INTEGER parameters and return value, otherwise it will crash.
+ // Metadata is inspected dynamically (in execute). This is not the fastest method.
FB_UDR_EXECUTE_DYNAMIC_FUNCTION
{
- ///AutoDispose<IStatus> status(master->getStatus());
+ // Get input and output metadata.
- const IParametersMetadata* params = metadata->getInputParameters(status);
+ IMessageMetadata* inMetadata = metadata->getInputMetadata(status);
StatusException::check(status->get());
- unsigned count = params->getCount(status);
+ IMessageMetadata* outMetadata = metadata->getOutputMetadata(status);
StatusException::check(status->get());
- MessageImpl inMessage(count, in);
+ // Get count of input parameters.
+ unsigned inCount = inMetadata->getCount(status);
+ StatusException::check(status->get());
- MessageImpl outMessage(1, out);
- ParamDesc<ISC_LONG> retDesc(outMessage);
+ // Get null offset of the return value.
- int ret = 0;
+ unsigned outNullOffset = outMetadata->getNullOffset(status, 0);
+ StatusException::check(status->get());
- for (unsigned i = 0; i < count; ++i)
+ // By default, the return value is NOT NULL.
+ ///*(ISC_SHORT*) (out + outNullOffset) = FB_FALSE;
+
+ // Get offset of the return value.
+ unsigned outOffset = outMetadata->getOffset(status, 0);
+ StatusException::check(status->get());
+
+ // Get a reference to the return value.
+ ISC_LONG& ret = *(ISC_LONG*) (out + outOffset);
+
+ // By default, the return value is 0.
+ ///ret = 0;
+
+ for (unsigned i = 0; i < inCount; ++i)
{
- ParamDesc<ISC_LONG> numDesc(inMessage);
+ // Get null offset of the i-th input parameter.
+ unsigned nullOffset = inMetadata->getNullOffset(status, i);
+ StatusException::check(status->get());
- if (inMessage.isNull(numDesc))
+ // If the i-th input parameter is NULL, set the output to NULL and finish.
+ if (*(ISC_SHORT*) (in + nullOffset))
{
- outMessage.setNull(retDesc, true);
- return;
+ *(ISC_SHORT*) (out + outNullOffset) = FB_TRUE;
+ // Important: we should not return without release the metadata objects.
+ break;
}
- else
- ret += inMessage[numDesc];
+
+ // Get the offset of the i-th input parameter.
+ unsigned offset = inMetadata->getOffset(status, i);
+ StatusException::check(status->get());
+
+ // Read the i-th input parameter value and sum it in the referenced return value.
+ ret += *(ISC_LONG*) (in + offset);
}
- outMessage[retDesc] = ret;
+ // Release refcounted objects.
+ inMetadata->release();
+ outMetadata->release();
}
FB_UDR_END_FUNCTION
@@ -660,29 +243,61 @@
engine udr;
***/
FB_UDR_BEGIN_PROCEDURE(gen_rows)
- FB_UDR_EXECUTE_DYNAMIC_PROCEDURE
+ // Procedure variables.
+ unsigned inOffsetStart, inOffsetEnd, outOffset;
+
+ /*** Procedure destructor.
+ ~FB_UDR_PROCEDURE(gen_rows)()
{
- MessageImpl inMessage(2, in);
- ParamDesc<ISC_LONG> startDesc(inMessage);
- ParamDesc<ISC_LONG> endDesc(inMessage);
+ }
+ ***/
- counter = inMessage[startDesc];
- end = inMessage[endDesc];
+ // Get offsets once per procedure.
+ FB_UDR_INITIALIZE
+ {
+ IMessageMetadata* inMetadata = metadata->getInputMetadata(status);
+ StatusException::check(status->get());
+
+ inOffsetStart = inMetadata->getOffset(status, 0);
+ StatusException::check(status->get());
+
+ inOffsetEnd = inMetadata->getOffset(status, 1);
+ StatusException::check(status->get());
+
+ inMetadata->release();
+
+ IMessageMetadata* outMetadata = metadata->getOutputMetadata(status);
+ StatusException::check(status->get());
+
+ outOffset = outMetadata->getOffset(status, 0);
+ StatusException::check(status->get());
+
+ outMetadata->release();
}
+ FB_UDR_EXECUTE_DYNAMIC_PROCEDURE
+ {
+ counter = *(ISC_LONG*) (in + procedure->inOffsetStart);
+ end = *(ISC_LONG*) (in + procedure->inOffsetEnd);
+ }
+
FB_UDR_FETCH_PROCEDURE
{
if (counter > end)
return false;
- MessageImpl outMessage(1, out);
- ParamDesc<ISC_LONG> retDesc(outMessage);
+ *(ISC_LONG*) (out + procedure->outOffset) = counter++;
- outMessage[retDesc] = counter++;
-
return true;
}
+ /*** ResultSet destructor.
+ ~ResultSet()
+ {
+ }
+ ***/
+
+ // ResultSet variables.
ISC_LONG counter;
ISC_LONG end;
FB_UDR_END_PROCEDURE
@@ -795,6 +410,7 @@
FB_UDR_END_PROCEDURE
+#if 0 //// FIXME:
/***
Sample usage:
@@ -1234,3 +850,4 @@
XSQLDA* inSqlDa;
isc_stmt_handle stmtHandle;
FB_UDR_END_TRIGGER
+#endif
Modified: firebird/trunk/src/dsql/ExprNodes.cpp
===================================================================
--- firebird/trunk/src/dsql/ExprNodes.cpp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/dsql/ExprNodes.cpp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -10657,7 +10657,11 @@
CMP_impure(csb, function->getInputFormat()->fmt_length);
}
- fb_assert(function->getOutputFormat()->fmt_count == 3);
+ if (function->fun_external)
+ fb_assert(function->getOutputFormat()->fmt_count == 2);
+ else
+ fb_assert(function->getOutputFormat()->fmt_count == 3);
+
fb_assert(function->getOutputFormat()->fmt_length);
CMP_impure(csb, function->getOutputFormat()->fmt_length);
}
@@ -10745,6 +10749,13 @@
UCHAR* const inMsg = (UCHAR*) FB_ALIGN((IPTR) impure + sizeof(impure_value), FB_ALIGNMENT);
UCHAR* const outMsg = (UCHAR*) FB_ALIGN((IPTR) inMsg + inMsgLength, FB_ALIGNMENT);
+ if (function->fun_external)
+ {
+ // We must clear messages of external functions.
+ memset(inMsg, 0, inMsgLength);
+ memset(outMsg, 0, outMsgLength);
+ }
+
if (function->fun_inputs != 0)
{
const NestConst<ValueExprNode>* const sourceEnd = args->items.end();
@@ -10772,32 +10783,14 @@
}
}
- jrd_req* funcRequest = function->getStatement()->findRequest(tdbb);
+ jrd_tra* transaction = request->req_transaction;
+ const SLONG savePointNumber = transaction->tra_save_point ?
+ transaction->tra_save_point->sav_number : 0;
- // trace function execution start
- //// TODO: TraceProcExecute trace(tdbb, funcRequest, request, inputTargets);
-
- // Catch errors so we can unwind cleanly.
-
- try
+ if (function->fun_external)
{
- Jrd::ContextPoolHolder context(tdbb, funcRequest->req_pool); // Save the old pool.
+ function->fun_external->execute(tdbb, inMsg, outMsg);
- jrd_tra* transaction = request->req_transaction;
- const SLONG savePointNumber = transaction->tra_save_point ?
- transaction->tra_save_point->sav_number : 0;
-
- funcRequest->req_timestamp = request->req_timestamp;
-
- EXE_start(tdbb, funcRequest, transaction);
-
- if (inMsgLength != 0)
- EXE_send(tdbb, funcRequest, 0, inMsgLength, inMsg);
-
- EXE_receive(tdbb, funcRequest, 1, outMsgLength, outMsg);
-
- // Clean up all savepoints started during execution of the procedure.
-
if (transaction != attachment->getSysTransaction())
{
for (const Savepoint* savePoint = transaction->tra_save_point;
@@ -10808,30 +10801,65 @@
}
}
}
- catch (const Exception& ex)
+ else
{
- /*** TODO:
- const bool noPriv = (ex.stuff_exception(tdbb->tdbb_status_vector) == isc_no_priv);
- trace.finish(false, noPriv ? res_unauthorized : res_failed);
- ***/
+ jrd_req* funcRequest = function->getStatement()->findRequest(tdbb);
+ // trace function execution start
+ //// TODO: TraceProcExecute trace(tdbb, funcRequest, request, inputTargets);
+
+ // Catch errors so we can unwind cleanly.
+
+ try
+ {
+ Jrd::ContextPoolHolder context(tdbb, funcRequest->req_pool); // Save the old pool.
+
+ funcRequest->req_timestamp = request->req_timestamp;
+
+ EXE_start(tdbb, funcRequest, transaction);
+
+ if (inMsgLength != 0)
+ EXE_send(tdbb, funcRequest, 0, inMsgLength, inMsg);
+
+ EXE_receive(tdbb, funcRequest, 1, outMsgLength, outMsg);
+
+ // Clean up all savepoints started during execution of the procedure.
+
+ if (transaction != attachment->getSysTransaction())
+ {
+ for (const Savepoint* savePoint = transaction->tra_save_point;
+ savePoint && savePointNumber < savePoint->sav_number;
+ savePoint = transaction->tra_save_point)
+ {
+ VIO_verb_cleanup(tdbb, transaction);
+ }
+ }
+ }
+ catch (const Exception& ex)
+ {
+ /*** TODO:
+ const bool noPriv = (ex.stuff_exception(tdbb->tdbb_status_vector) == isc_no_priv);
+ trace.finish(false, noPriv ? res_unauthorized : res_failed);
+ ***/
+
+ tdbb->setRequest(request);
+ EXE_unwind(tdbb, funcRequest);
+ funcRequest->req_attachment = NULL;
+ funcRequest->req_flags &= ~(req_in_use | req_proc_fetch);
+ funcRequest->req_timestamp.invalidate();
+ throw;
+ }
+
+ //// TODO: trace.finish(false, res_successful);
+
+ EXE_unwind(tdbb, funcRequest);
tdbb->setRequest(request);
- EXE_unwind(tdbb, funcRequest);
+
funcRequest->req_attachment = NULL;
funcRequest->req_flags &= ~(req_in_use | req_proc_fetch);
funcRequest->req_timestamp.invalidate();
- throw;
}
- //// TODO: trace.finish(false, res_successful);
-
- EXE_unwind(tdbb, funcRequest);
- tdbb->setRequest(request);
-
- funcRequest->req_attachment = NULL;
- funcRequest->req_flags &= ~(req_in_use | req_proc_fetch);
- funcRequest->req_timestamp.invalidate();
-
const dsc* fmtDesc = function->getOutputFormat()->fmt_desc.begin();
const ULONG nullOffset = (IPTR) fmtDesc[1].dsc_address;
SSHORT* const nullPtr = reinterpret_cast<SSHORT*>(outMsg + nullOffset);
Modified: firebird/trunk/src/dsql/StmtNodes.cpp
===================================================================
--- firebird/trunk/src/dsql/StmtNodes.cpp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/dsql/StmtNodes.cpp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -1564,7 +1564,7 @@
PAR_error(csb, Arg::Gds(isc_prc_out_param_mismatch) << name);
Format* format = Format::newFormat(pool, paramArray.getCount());
- subProc->prc_format = format;
+ subProc->prc_record_format = format;
format->fmt_length = FLAG_BYTES(format->fmt_count);
for (USHORT i = 0; i < count - 1u; i += 2u)
@@ -1754,7 +1754,7 @@
}
fb_assert(subCsb->csb_rpt.getCount() >= 2);
- routine->prc_output_msg = subCsb->csb_rpt[1].csb_message;
+ ///routine->prc_output_msg = subCsb->csb_rpt[1].csb_message;
return this;
}
@@ -2717,16 +2717,6 @@
{
Jrd::Attachment* attachment = tdbb->getAttachment();
- if (inputSources)
- {
- const NestConst<ValueExprNode>* const sourceEnd = inputSources->items.end();
- const NestConst<ValueExprNode>* sourcePtr = inputSources->items.begin();
- const NestConst<ValueExprNode>* targetPtr = inputTargets->items.begin();
-
- for (; sourcePtr != sourceEnd; ++sourcePtr, ++targetPtr)
- EXE_assignment(tdbb, *sourcePtr, *targetPtr);
- }
-
ULONG inMsgLength = 0;
UCHAR* inMsg = NULL;
@@ -2739,6 +2729,7 @@
const Format* format = NULL;
ULONG outMsgLength = 0;
UCHAR* outMsg = NULL;
+ Array<UCHAR> tempBuffer;
if (outputMessage)
{
@@ -2746,41 +2737,44 @@
outMsgLength = format->fmt_length;
outMsg = request->getImpure<UCHAR>(outputMessage->impureOffset);
}
-
- jrd_req* procRequest = procedure->getStatement()->findRequest(tdbb);
-
- // trace procedure execution start
- TraceProcExecute trace(tdbb, procRequest, request, inputTargets);
-
- Array<UCHAR> tempBuffer;
-
- if (!outputMessage)
+ else
{
- format = procedure->prc_output_msg->format;
+ ///format = procedure->prc_output_msg->format;
+ format = procedure->getOutputFormat();
outMsgLength = format->fmt_length;
outMsg = tempBuffer.getBuffer(outMsgLength + FB_DOUBLE_ALIGN - 1);
outMsg = (UCHAR*) FB_ALIGN((U_IPTR) outMsg, FB_DOUBLE_ALIGN);
}
- // Catch errors so we can unwind cleanly.
+ if (procedure->getExternal())
+ {
+ // We must clear messages of external procedures.
+ memset(inMsg, 0, inMsgLength);
+ memset(outMsg, 0, outMsgLength);
+ }
- try
+ if (inputSources)
{
- Jrd::ContextPoolHolder context(tdbb, procRequest->req_pool); // Save the old pool.
+ const NestConst<ValueExprNode>* const sourceEnd = inputSources->items.end();
+ const NestConst<ValueExprNode>* sourcePtr = inputSources->items.begin();
+ const NestConst<ValueExprNode>* targetPtr = inputTargets->items.begin();
- jrd_tra* transaction = request->req_transaction;
- const SLONG savePointNumber = transaction->tra_save_point ?
- transaction->tra_save_point->sav_number : 0;
+ for (; sourcePtr != sourceEnd; ++sourcePtr, ++targetPtr)
+ EXE_assignment(tdbb, *sourcePtr, *targetPtr);
+ }
- procRequest->req_timestamp = request->req_timestamp;
+ jrd_tra* transaction = request->req_transaction;
+ const SLONG savePointNumber = transaction->tra_save_point ?
+ transaction->tra_save_point->sav_number : 0;
- EXE_start(tdbb, procRequest, transaction);
+ if (procedure->getExternal())
+ {
+ { // scope
+ AutoPtr<ExtEngineManager::ResultSet> resultSet(procedure->getExternal()->open(
+ tdbb, inMsg, outMsg));
+ resultSet->fetch(tdbb);
+ }
- if (inputMessage)
- EXE_send(tdbb, procRequest, 0, inMsgLength, inMsg);
-
- EXE_receive(tdbb, procRequest, 1, outMsgLength, outMsg);
-
// Clean up all savepoints started during execution of the procedure.
if (transaction != attachment->getSysTransaction())
@@ -2793,25 +2787,64 @@
}
}
}
- catch (const Exception& ex)
+ else
{
- const bool noPriv = (ex.stuff_exception(tdbb->tdbb_status_vector) == isc_no_priv);
- trace.finish(false, noPriv ? res_unauthorized : res_failed);
+ jrd_req* procRequest = procedure->getStatement()->findRequest(tdbb);
+ // trace procedure execution start
+ TraceProcExecute trace(tdbb, procRequest, request, inputTargets);
+
+ // Catch errors so we can unwind cleanly.
+
+ try
+ {
+ Jrd::ContextPoolHolder context(tdbb, procRequest->req_pool); // Save the old pool.
+
+ procRequest->req_timestamp = request->req_timestamp;
+
+ EXE_start(tdbb, procRequest, transaction);
+
+ if (inputMessage)
+ EXE_send(tdbb, procRequest, 0, inMsgLength, inMsg);
+
+ EXE_receive(tdbb, procRequest, 1, outMsgLength, outMsg);
+
+ // Clean up all savepoints started during execution of the procedure.
+
+ if (transaction != attachment->getSysTransaction())
+ {
+ for (const Savepoint* savePoint = transaction->tra_save_point;
+ savePoint && savePointNumber < savePoint->sav_number;
+ savePoint = transaction->tra_save_point)
+ {
+ VIO_verb_cleanup(tdbb, transaction);
+ }
+ }
+ }
+ catch (const Exception& ex)
+ {
+ const bool noPriv = (ex.stuff_exception(tdbb->tdbb_status_vector) == isc_no_priv);
+ trace.finish(false, noPriv ? res_unauthorized : res_failed);
+
+ tdbb->setRequest(request);
+ EXE_unwind(tdbb, procRequest);
+ procRequest->req_attachment = NULL;
+ procRequest->req_flags &= ~(req_in_use | req_proc_fetch);
+ procRequest->req_timestamp.invalidate();
+ throw;
+ }
+
+ // trace procedure execution finish
+ trace.finish(false, res_successful);
+
+ EXE_unwind(tdbb, procRequest);
tdbb->setRequest(request);
- EXE_unwind(tdbb, procRequest);
+
procRequest->req_attachment = NULL;
procRequest->req_flags &= ~(req_in_use | req_proc_fetch);
procRequest->req_timestamp.invalidate();
- throw;
}
- // trace procedure execution finish
- trace.finish(false, res_successful);
-
- EXE_unwind(tdbb, procRequest);
- tdbb->setRequest(request);
-
if (outputSources)
{
const NestConst<ValueExprNode>* const sourceEnd = outputSources->items.end();
@@ -2821,10 +2854,6 @@
for (; sourcePtr != sourceEnd; ++sourcePtr, ++targetPtr)
EXE_assignment(tdbb, *sourcePtr, *targetPtr);
}
-
- procRequest->req_attachment = NULL;
- procRequest->req_flags &= ~(req_in_use | req_proc_fetch);
- procRequest->req_timestamp.invalidate();
}
Modified: firebird/trunk/src/include/firebird/ExternalEngine.h
===================================================================
--- firebird/trunk/src/include/firebird/ExternalEngine.h 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/include/firebird/ExternalEngine.h 2013-03-04 01:42:58 UTC (rev 57719)
@@ -38,14 +38,6 @@
class ExternalEngine;
-class IRoutineMessage : public IVersioned
-{
-public:
- virtual void FB_CARG set(const unsigned char* blr, unsigned blrLength, unsigned bufferLength) = 0;
-};
-#define FB_ROUTINE_MESSAGE_VERSION (FB_VERSIONED_VERSION + 1)
-
-
class ITriggerMessage : public IVersioned
{
public:
@@ -205,9 +197,11 @@
// Called when engine wants to load object in the cache. Objects are disposed when
// going out of the cache.
virtual ExternalFunction* FB_CALL makeFunction(IStatus* status, ExternalContext* context,
- const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg) = 0;
+ const IRoutineMetadata* metadata,
+ IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) = 0;
virtual ExternalProcedure* FB_CALL makeProcedure(IStatus* status, ExternalContext* context,
- const IRoutineMetadata* metadata, IRoutineMessage* inMsg, IRoutineMessage* outMsg) = 0;
+ const IRoutineMetadata* metadata,
+ IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) = 0;
virtual ExternalTrigger* FB_CALL makeTrigger(IStatus* status, ExternalContext* context,
const IRoutineMetadata* metadata, ITriggerMessage* triggerMsg) = 0;
};
Modified: firebird/trunk/src/include/firebird/Message.h
===================================================================
--- firebird/trunk/src/include/firebird/Message.h 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/include/firebird/Message.h 2013-03-04 01:42:58 UTC (rev 57719)
@@ -24,16 +24,14 @@
#define FIREBIRD_MESSAGE_H
#include "ibase.h"
-#include "firebird/impl/boost/preprocessor/seq/for_each_i.hpp"
+#include "./Provider.h"
+#include "./impl/boost/preprocessor/seq/for_each_i.hpp"
#include <assert.h>
#include <time.h>
#include <string.h>
#define FB_MESSAGE(name, fields) \
- struct name \
- { \
- FB_MESSAGE_I(name, 2, FB_BOOST_PP_CAT(FB_MESSAGE_X fields, 0)) \
- }
+ FB_MESSAGE_I(name, 2, FB_BOOST_PP_CAT(FB_MESSAGE_X fields, 0))
#define FB_MESSAGE_X(x, y) ((x, y)) FB_MESSAGE_Y
#define FB_MESSAGE_Y(x, y) ((x, y)) FB_MESSAGE_X
@@ -53,61 +51,136 @@
#define FB_TRIGGER_MESSAGE_Y0
#define FB_MESSAGE_I(name, size, fields) \
- static const unsigned char* getBlr(unsigned* length) \
+ struct name \
{ \
- static const unsigned char blr[] = { \
- blr_version5, \
- blr_begin, \
- blr_message, 0, \
- (2 * (FB_BOOST_PP_SEQ_SIZE(fields))) & 0xFF, \
- (2 * (FB_BOOST_PP_SEQ_SIZE(fields))) >> 8, \
- FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_BLR, size, fields) \
- blr_end, \
- blr_eoc \
+ struct Type \
+ { \
+ FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_FIELD, size, fields) \
}; \
- *length = sizeof(blr); \
- return blr; \
- } \
- \
- static unsigned getSize() \
- { \
- return (unsigned)(size_t) (&((name*) 0)->FB_BOOST_PP_CAT( \
- FB_BOOST_PP_TUPLE_ELEM(size, 1, \
- FB_BOOST_PP_SEQ_ELEM(FB_BOOST_PP_DEC(FB_BOOST_PP_SEQ_SIZE(fields)), fields)), \
- Null) - 0) + sizeof(ISC_SHORT); \
- } \
- \
- void clear() \
- { \
- memset(this, 0, sizeof(*this)); \
- } \
- \
- FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_FIELD, size, fields)
+ \
+ static void setup(IStatus* status, ::Firebird::IMetadataBuilder* builder) \
+ { \
+ unsigned index = 0; \
+ FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_META, size, fields) \
+ } \
+ \
+ name(::Firebird::IMaster* master) \
+ : desc(master, FB_BOOST_PP_SEQ_SIZE(fields), &setup) \
+ { \
+ } \
+ \
+ ::Firebird::IMessageMetadata* getMetadata() const \
+ { \
+ return desc.getMetadata(); \
+ } \
+ \
+ void clear() \
+ { \
+ memset(&data, 0, sizeof(data)); \
+ } \
+ \
+ Type* getData() \
+ { \
+ return &data; \
+ } \
+ \
+ const Type* getData() const \
+ { \
+ return &data; \
+ } \
+ \
+ Type* operator ->() \
+ { \
+ return getData(); \
+ } \
+ \
+ const Type* operator ->() const \
+ { \
+ return getData(); \
+ } \
+ \
+ Type data; \
+ ::Firebird::MessageDesc desc; \
+ }
#define FB_MESSAGE_FIELD(r, _, i, xy) \
FB_BOOST_PP_CAT(FB_TYPE_, FB_BOOST_PP_TUPLE_ELEM(_, 0, xy)) FB_BOOST_PP_TUPLE_ELEM(_, 1, xy); \
ISC_SHORT FB_BOOST_PP_CAT(FB_BOOST_PP_TUPLE_ELEM(_, 1, xy), Null);
-#define FB_MESSAGE_BLR(r, _, i, xy) \
- FB_BOOST_PP_CAT(FB_BLR_, FB_BOOST_PP_TUPLE_ELEM(_, 0, xy)), \
- FB_BLR_FB_SMALLINT,
+#define FB_MESSAGE_META(r, _, i, xy) \
+ FB_BOOST_PP_CAT(FB_META_, FB_BOOST_PP_TUPLE_ELEM(_, 0, xy))
-#define FB_BLR_FB_SCALED_SMALLINT(scale) blr_short, (scale)
-#define FB_BLR_FB_SCALED_INTEGER(scale) blr_long, (scale)
-#define FB_BLR_FB_SCALED_BIGINT(scale) blr_int64, (scale)
-#define FB_BLR_FB_SMALLINT FB_BLR_FB_SCALED_SMALLINT(0)
-#define FB_BLR_FB_INTEGER FB_BLR_FB_SCALED_INTEGER(0)
-#define FB_BLR_FB_BIGINT FB_BLR_FB_SCALED_BIGINT(0)
-#define FB_BLR_FB_FLOAT blr_float
-#define FB_BLR_FB_DOUBLE blr_double
-#define FB_BLR_FB_BLOB blr_blob2, 0, 0, 0, 0
-#define FB_BLR_FB_BOOLEAN blr_bool
-#define FB_BLR_FB_DATE blr_sql_date
-#define FB_BLR_FB_TIME blr_sql_time
-#define FB_BLR_FB_TIMESTAMP blr_timestamp
-#define FB_BLR_FB_CHAR(len) blr_text2, 0, 0, (len) & 0xFF, (len) >> 8
-#define FB_BLR_FB_VARCHAR(len) blr_varying2, 0, 0, (len) & 0xFF, (len) >> 8
+// Types - metadata
+#define FB_META_FB_SCALED_SMALLINT(scale) \
+ builder->setType(status, index, SQL_SHORT); \
+ builder->setLength(status, index, sizeof(ISC_SHORT)); \
+ builder->setScale(status, index, scale); \
+ ++index;
+
+#define FB_META_FB_SCALED_INTEGER(scale) \
+ builder->setType(status, index, SQL_LONG); \
+ builder->setLength(status, index, sizeof(ISC_LONG)); \
+ builder->setScale(status, index, scale); \
+ ++index;
+
+#define FB_META_FB_SCALED_BIGINT(scale) \
+ builder->setType(status, index, SQL_INT64); \
+ builder->setLength(status, index, sizeof(ISC_INT64)); \
+ builder->setScale(status, index, scale); \
+ ++index;
+
+#define FB_META_FB_FLOAT \
+ builder->setType(status, index, SQL_FLOAT); \
+ builder->setLength(status, index, sizeof(float)); \
+ ++index;
+
+#define FB_META_FB_DOUBLE \
+ builder->setType(status, index, SQL_DOUBLE); \
+ builder->setLength(status, index, sizeof(double)); \
+ ++index;
+
+#define FB_META_FB_BLOB \
+ builder->setType(status, index, SQL_BLOB); \
+ builder->setLength(status, index, sizeof(ISC_QUAD)); \
+ ++index;
+
+#define FB_META_FB_BOOLEAN \
+ builder->setType(status, index, SQL_BOOLEAN); \
+ builder->setLength(status, index, sizeof(ISC_BOOLEAN)); \
+ ++index;
+
+#define FB_META_FB_DATE \
+ builder->setType(status, index, SQL_DATE); \
+ builder->setLength(status, index, sizeof(FbDate)); \
+ ++index;
+
+#define FB_META_FB_TIME \
+ builder->setType(status, index, SQL_TIME); \
+ builder->setLength(status, index, sizeof(FbTime)); \
+ ++index;
+
+#define FB_META_FB_TIMESTAMP \
+ builder->setType(status, index, SQL_TIMESTAMP); \
+ builder->setLength(status, index, sizeof(FbTimestamp)); \
+ ++index;
+
+#define FB_META_FB_CHAR(len) \
+ builder->setType(status, index, SQL_TEXT); \
+ builder->setLength(status, index, len); \
+ ++index;
+
+#define FB_META_FB_VARCHAR(len) \
+ builder->setType(status, index, SQL_VARYING); \
+ builder->setLength(status, index, len); \
+ ++index;
+
+#define FB_META_FB_SMALLINT FB_META_FB_SCALED_SMALLINT(0)
+#define FB_META_FB_INTEGER FB_META_FB_SCALED_INTEGER(0)
+#define FB_META_FB_BIGINT FB_META_FB_SCALED_BIGINT(0)
+
+// Types - struct
+
#define FB_TYPE_FB_SCALED_SMALLINT(x) ISC_SHORT
#define FB_TYPE_FB_SCALED_INTEGER(x) ISC_LONG
#define FB_TYPE_FB_SCALED_BIGINT(x) ISC_INT64
@@ -322,7 +395,37 @@
FbTime time;
};
+class MessageDesc
+{
+public:
+ MessageDesc(IMaster* master, unsigned count, void (*setup)(IStatus*, IMetadataBuilder*))
+ {
+ IStatus* status = master->getStatus();
+ IMetadataBuilder* builder = master->getMetadataBuilder(status, count);
+ setup(status, builder);
+
+ metadata = builder->getMetadata(status);
+
+ builder->release();
+ status->dispose();
+ }
+
+ ~MessageDesc()
+ {
+ metadata->release();
+ }
+
+ IMessageMetadata* getMetadata() const
+ {
+ return metadata;
+ }
+
+private:
+ IMessageMetadata* metadata;
+};
+
+
} // namespace Firebird
#endif // FIREBIRD_MESSAGE_H
Modified: firebird/trunk/src/include/firebird/UdrCppEngine.h
===================================================================
--- firebird/trunk/src/include/firebird/UdrCppEngine.h 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/include/firebird/UdrCppEngine.h 2013-03-04 01:42:58 UTC (rev 57719)
@@ -61,10 +61,10 @@
};
#define FB_UDR_EXECUTE_DYNAMIC_FUNCTION \
- typedef void* InMessage; \
- typedef void* OutMessage; \
+ FB_UDR__DYNAMIC_TYPE(InMessage); \
+ FB_UDR__DYNAMIC_TYPE(OutMessage); \
\
- FB_UDR_EXECUTE__FUNCTION
+ FB_UDR__EXECUTE_FUNCTION
#define FB_UDR_EXECUTE_MESSAGE_FUNCTION(inputs, output) \
FB_MESSAGE(InMessage, \
@@ -74,29 +74,29 @@
output \
); \
\
- FB_UDR_EXECUTE__FUNCTION
+ FB_UDR__EXECUTE_FUNCTION
#define FB_UDR_EXECUTE_MESSAGE_FUNCTION_OUT(outputs) \
- typedef void* InMessage; \
+ FB_UDR__DYNAMIC_TYPE(InMessage); \
FB_MESSAGE(OutMessage, \
outputs \
); \
\
- FB_UDR_EXECUTE__FUNCTION
+ FB_UDR__EXECUTE_FUNCTION
-#define FB_UDR_EXECUTE__FUNCTION \
+#define FB_UDR__EXECUTE_FUNCTION \
virtual void FB_CALL execute(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
void* in, void* out) \
{ \
try \
{ \
- internalExecute(status, context, (InMessage*) in, (OutMessage*) out); \
+ internalExecute(status, context, (InMessage::Type*) in, (OutMessage::Type*) out); \
} \
FB_UDR__CATCH \
} \
\
void internalExecute(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
- InMessage* in, OutMessage* out)
+ InMessage::Type* in, OutMessage::Type* out)
#define FB_UDR_BEGIN_PROCEDURE(name) \
@@ -118,10 +118,10 @@
};
#define FB_UDR_EXECUTE_DYNAMIC_PROCEDURE \
- typedef void* InMessage; \
- typedef void* OutMessage; \
+ FB_UDR__DYNAMIC_TYPE(InMessage); \
+ FB_UDR__DYNAMIC_TYPE(OutMessage); \
\
- FB_UDR_EXECUTE__PROCEDURE
+ FB_UDR__EXECUTE_PROCEDURE
#define FB_UDR_EXECUTE_MESSAGE_PROCEDURE(inputs, outputs) \
FB_MESSAGE(InMessage, \
@@ -131,31 +131,31 @@
outputs \
); \
\
- FB_UDR_EXECUTE__PROCEDURE
+ FB_UDR__EXECUTE_PROCEDURE
#define FB_UDR_EXECUTE_MESSAGE_PROCEDURE_IN(inputs) \
FB_MESSAGE(InMessage, \
inputs \
); \
- typedef void* OutMessage; \
+ FB_UDR__DYNAMIC_TYPE(OutMessage); \
\
- FB_UDR_EXECUTE__PROCEDURE
+ FB_UDR__EXECUTE_PROCEDURE
#define FB_UDR_EXECUTE_MESSAGE_PROCEDURE_OUT(outputs) \
- typedef void* InMessage; \
+ FB_UDR__DYNAMIC_TYPE(InMessage); \
FB_MESSAGE(OutMessage, \
outputs \
); \
\
- FB_UDR_EXECUTE__PROCEDURE
+ FB_UDR__EXECUTE_PROCEDURE
-#define FB_UDR_EXECUTE__PROCEDURE \
+#define FB_UDR__EXECUTE_PROCEDURE \
virtual ::Firebird::ExternalResultSet* FB_CALL open(::Firebird::IStatus* status, \
::Firebird::ExternalContext* context, void* in, void* out) \
{ \
try \
{ \
- return new ResultSet(status, context, this, (InMessage*) in, (OutMessage*) out); \
+ return new ResultSet(status, context, this, (InMessage::Type*) in, (OutMessage::Type*) out); \
} \
FB_UDR__CATCH \
\
@@ -166,7 +166,7 @@
{ \
public: \
ResultSet(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
- This* const procedure, InMessage* const in, OutMessage* const out) \
+ This* const procedure, InMessage::Type* const in, OutMessage::Type* const out) \
: ::Firebird::Udr::ResultSet<ResultSet, This, InMessage, OutMessage>( \
context, procedure, in, out)
@@ -204,16 +204,16 @@
#define FB_UDR_EXECUTE_DYNAMIC_TRIGGER \
typedef void* FieldsMessage; \
\
- FB_UDR_EXECUTE__TRIGGER
+ FB_UDR__EXECUTE_TRIGGER
#define FB_UDR_EXECUTE_MESSAGE_TRIGGER(fields) \
FB_TRIGGER_MESSAGE(FieldsMessage, \
fields \
); \
\
- FB_UDR_EXECUTE__TRIGGER
+ FB_UDR__EXECUTE_TRIGGER
-#define FB_UDR_EXECUTE__TRIGGER \
+#define FB_UDR__EXECUTE_TRIGGER \
virtual void FB_CALL execute(::Firebird::IStatus* status, ::Firebird::ExternalContext* context, \
::Firebird::ExternalTrigger::Action action, void* oldFields, void* newFields) \
{ \
@@ -241,6 +241,14 @@
void internalInitialize(::Firebird::IStatus* status, ::Firebird::ExternalContext* context)
+#define FB_UDR__DYNAMIC_TYPE(name) \
+ struct name \
+ { \
+ typedef unsigned char Type; \
+ static void setup(::Firebird::IStatus*, ::Firebird::IMetadataBuilder*) {} \
+ }
+
+
#define FB_UDR__CATCH \
catch (const ::Firebird::Udr::StatusException& e) \
{ \
@@ -437,7 +445,7 @@
{
public:
ResultSet(ExternalContext* aContext, Procedure* aProcedure,
- InMessage* aIn, OutMessage* aOut)
+ typename InMessage::Type* aIn, typename OutMessage::Type* aOut)
: context(aContext),
procedure(aProcedure),
in(aIn),
@@ -454,8 +462,8 @@
protected:
ExternalContext* const context;
Procedure* const procedure;
- InMessage* const in;
- OutMessage* const out;
+ typename InMessage::Type* const in;
+ typename OutMessage::Type* const out;
};
@@ -572,11 +580,11 @@
fbUdrRegFunction(name, this);
}
- virtual void setup(IStatus* /*status*/, ExternalContext* /*context*/,
- const IRoutineMetadata* /*metadata*/, IRoutineMessage* in, IRoutineMessage* out)
+ virtual void setup(IStatus* status, ExternalContext* /*context*/,
+ const IRoutineMetadata* /*metadata*/, IMetadataBuilder* in, IMetadataBuilder* out)
{
- setBlr(in, (typename T::InMessage*) 0);
- setBlr(out, (typename T::OutMessage*) 0);
+ T::InMessage::setup(status, in);
+ T::OutMessage::setup(status, out);
}
virtual ExternalFunction* FB_CALL newItem(IStatus* status, ExternalContext* context,
@@ -586,18 +594,6 @@
obj->initialize(status, context);
return obj;
}
-
-private:
- template <typename MessageType> void setBlr(IRoutineMessage* blrMessage, MessageType*)
- {
- unsigned blrLength;
- const unsigned char* blr = MessageType::getBlr(&blrLength);
- blrMessage->set(blr, blrLength, MessageType::getSize());
- }
-
- void setBlr(IRoutineMessage* /*blrMessage*/, void**)
- {
- }
};
@@ -609,11 +605,11 @@
fbUdrRegProcedure(name, this);
}
- virtual void setup(IStatus* /*status*/, ExternalContext* /*context*/,
- const IRoutineMetadata* /*metadata*/, IRoutineMessage* in, IRoutineMessage* out)
+ virtual void setup(IStatus* status, ExternalContext* /*context*/,
+ const IRoutineMetadata* /*metadata*/, IMetadataBuilder* in, IMetadataBuilder* out)
{
- setBlr(in, (typename T::InMessage*) 0);
- setBlr(out, (typename T::OutMessage*) 0);
+ T::InMessage::setup(status, in);
+ T::OutMessage::setup(status, out);
}
virtual ExternalProcedure* FB_CALL newItem(IStatus* status, ExternalContext* context,
@@ -623,18 +619,6 @@
obj->initialize(status, context);
return obj;
}
-
-private:
- template <typename MessageType> void setBlr(IRoutineMessage* blrMessage, MessageType*)
- {
- unsigned blrLength;
- const unsigned char* blr = MessageType::getBlr(&blrLength);
- blrMessage->set(blr, blrLength, MessageType::getSize());
- }
-
- void setBlr(IRoutineMessage* /*blrMessage*/, void**)
- {
- }
};
@@ -646,10 +630,10 @@
fbUdrRegTrigger(name, this);
}
- virtual void setup(IStatus* /*status*/, ExternalContext* /*context*/,
+ virtual void setup(IStatus* status, ExternalContext* /*context*/,
const IRoutineMetadata* /*metadata*/, ITriggerMessage* fields)
{
- setBlr(fields, (typename T::FieldsMessage*) 0);
+ T::FieldsMessage::setup(status, fields);
}
virtual ExternalTrigger* FB_CALL newItem(IStatus* status, ExternalContext* context,
@@ -659,20 +643,6 @@
obj->initialize(status, context);
return obj;
}
-
-private:
- template <typename MessageType> void setBlr(ITriggerMessage* blrMessage, MessageType*)
- {
- unsigned blrLength, namesCount;
- const unsigned char* blr = MessageType::getBlr(&blrLength);
- const char** names = MessageType::getNames(&namesCount);
-
- blrMessage->set(blr, blrLength, MessageType::getSize(), names, namesCount);
- }
-
- void setBlr(ITriggerMessage* /*blrMessage*/, void**)
- {
- }
};
Modified: firebird/trunk/src/include/firebird/UdrEngine.h
===================================================================
--- firebird/trunk/src/include/firebird/UdrEngine.h 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/include/firebird/UdrEngine.h 2013-03-04 01:42:58 UTC (rev 57719)
@@ -40,7 +40,7 @@
{
public:
virtual void setup(IStatus* status, ExternalContext* context, const IRoutineMetadata* metadata,
- IRoutineMessage* in, IRoutineMessage* out) = 0;
+ IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) = 0;
virtual ExternalFunction* FB_CALL newItem(IStatus* status, ExternalContext* context,
const IRoutineMetadata* metadata) = 0;
};
@@ -49,7 +49,7 @@
{
public:
virtual void setup(IStatus* status, ExternalContext* context, const IRoutineMetadata* metadata,
- IRoutineMessage* in, IRoutineMessage* out) = 0;
+ IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) = 0;
virtual ExternalProcedure* FB_CALL newItem(IStatus* status, ExternalContext* context,
const IRoutineMetadata* metadata) = 0;
};
Modified: firebird/trunk/src/jrd/ExtEngineManager.cpp
===================================================================
--- firebird/trunk/src/jrd/ExtEngineManager.cpp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/jrd/ExtEngineManager.cpp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -58,8 +58,52 @@
namespace Jrd {
-MakeUpgradeInfo<> upInfo;
+static MakeUpgradeInfo<> upInfo;
+
+static Format* createFormat(MemoryPool& pool, IMessageMetadata* params)
+{
+ LocalStatus status;
+
+ unsigned count = params->getCount(&status);
+ status.check();
+
+ Format* format = Format::newFormat(pool, count * 2);
+ unsigned runOffset = 0;
+
+ dsc* desc = format->fmt_desc.begin();
+
+ for (unsigned i = 0; i < count; ++i)
+ {
+ unsigned descOffset, nullOffset, descDtype, descLength;
+
+ runOffset = fb_utils::sqlTypeToDsc(runOffset, params->getType(&status, i),
+ params->getLength(&status, i), &descDtype, &descLength,
+ &descOffset, &nullOffset);
+ status.check();
+
+ desc->clear();
+ desc->dsc_dtype = descDtype;
+ desc->dsc_length = descLength;
+ desc->dsc_scale = params->getScale(&status, i);
+ desc->dsc_sub_type = params->getSubType(&status, i);
+ desc->setTextType(params->getCharset(&status, i));
+ desc->dsc_address = (UCHAR*)(IPTR) descOffset;
+ desc->dsc_flags = (params->isNullable(&status, i) ? DSC_nullable : 0);
+
+ ++desc;
+ desc->makeShort(0, (SSHORT*)(IPTR) nullOffset);
+ status.check();
+
+ ++desc;
+ }
+
+ format->fmt_length = runOffset;
+
+ return format;
+}
+
+
template <typename T> class ExtEngineManager::ContextManager
{
public:
@@ -728,9 +772,8 @@
}
-ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, const Jrd::Function* udf,
- const MetaName& engine, const string& entryPoint, const string& body,
- RoutineMessage* inMsg, RoutineMessage* outMsg)
+void ExtEngineManager::makeFunction(thread_db* tdbb, Jrd::Function* udf,
+ const MetaName& engine, const string& entryPoint, const string& body)
{
string entryPointTrimmed = entryPoint;
entryPointTrimmed.trim();
@@ -749,9 +792,13 @@
metadata->name = udf->getName().identifier;
metadata->entryPoint = entryPointTrimmed;
metadata->body = body;
- metadata->inputParameters = new MsgMetadata;
- metadata->outputParameters = new MsgMetadata;
+ MsgMetadata* inMsg = new MsgMetadata;
+ metadata->inputParameters = inMsg;
+
+ MsgMetadata* outMsg = new MsgMetadata;
+ metadata->outputParameters = outMsg;
+
for (Array<NestConst<Parameter> >::const_iterator i = udf->getInputFields().begin();
i != udf->getInputFields().end();
++i)
@@ -759,13 +806,14 @@
SLONG sqlLen, sqlSubType, sqlScale, sqlType;
(*i)->prm_desc.getSqlInfo(&sqlLen, &sqlSubType, &sqlScale, &sqlType);
- StatementMetadata::Parameters::Item& item = metadata->inputParameters->items.add();
+ StatementMetadata::Parameters::Item& item = inMsg->items.add();
item.field = (*i)->prm_name.c_str();
item.type = sqlType;
item.subType = sqlSubType;
item.length = sqlLen;
item.scale = sqlScale;
item.nullable = (*i)->prm_nullable;
+ item.finished = true;
}
{ // scope
@@ -774,23 +822,33 @@
SLONG sqlLen, sqlSubType, sqlScale, sqlType;
i->prm_desc.getSqlInfo(&sqlLen, &sqlSubType, &sqlScale, &sqlType);
- StatementMetadata::Parameters::Item& item = metadata->outputParameters->items.add();
+ StatementMetadata::Parameters::Item& item = outMsg->items.add();
item.field = i->prm_name.c_str();
item.type = sqlType;
item.subType = sqlSubType;
item.length = sqlLen;
item.scale = sqlScale;
item.nullable = i->prm_nullable;
+ item.finished = true;
}
+ LocalStatus status;
+
+ RefPtr<IMetadataBuilder> inBuilder(metadata->inputParameters->getBuilder(&status));
+ inBuilder->release();
+ status.check();
+
+ RefPtr<IMetadataBuilder> outBuilder(metadata->outputParameters->getBuilder(&status));
+ outBuilder->release();
+ status.check();
+
ExternalFunction* externalFunction;
{ // scope
Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
- LocalStatus status;
externalFunction = attInfo->engine->makeFunction(&status, attInfo->context, metadata,
- inMsg, outMsg);
+ inBuilder, outBuilder);
status.check();
if (!externalFunction)
@@ -798,12 +856,21 @@
status_exception::raise(
Arg::Gds(isc_eem_func_not_returned) << udf->getName().toString() << engine);
}
+
+ metadata->inputParameters = inBuilder->getMetadata(&status);
+ status.check();
+
+ metadata->outputParameters = outBuilder->getMetadata(&status);
+ status.check();
}
try
{
- return FB_NEW(getPool()) Function(tdbb, this, attInfo->engine, metadata.release(),
- externalFunction, udf);
+ udf->setInputFormat(createFormat(pool, metadata->inputParameters));
+ udf->setOutputFormat(createFormat(pool, metadata->outputParameters));
+
+ udf->fun_external = FB_NEW(getPool()) Function(tdbb, this, attInfo->engine,
+ metadata.release(), externalFunction, udf);
}
catch (...)
{
@@ -814,9 +881,8 @@
}
-ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, const jrd_prc* prc,
- const MetaName& engine, const string& entryPoint, const string& body,
- RoutineMessage* inMsg, RoutineMessage* outMsg)
+void ExtEngineManager::makeProcedure(thread_db* tdbb, jrd_prc* prc,
+ const MetaName& engine, const string& entryPoint, const string& body)
{
string entryPointTrimmed = entryPoint;
entryPointTrimmed.trim();
@@ -835,9 +901,13 @@
metadata->name = prc->getName().identifier;
metadata->entryPoint = entryPointTrimmed;
metadata->body = body;
- metadata->inputParameters = new MsgMetadata;
- metadata->outputParameters = new MsgMetadata;
+ MsgMetadata* inMsg = new MsgMetadata;
+ metadata->inputParameters = inMsg;
+
+ MsgMetadata* outMsg = new MsgMetadata;
+ metadata->outputParameters = outMsg;
+
const Array<NestConst<Parameter> >* parameters[] = {
&prc->getInputFields(), &prc->getOutputFields()};
@@ -851,8 +921,7 @@
(*j)->prm_desc.getSqlInfo(&sqlLen, &sqlSubType, &sqlScale, &sqlType);
StatementMetadata::Parameters::Item& item = i == 1 ?
- metadata->outputParameters->items.add() :
- metadata->inputParameters->items.add();
+ outMsg->items.add() : inMsg->items.add();
item.field = (*j)->prm_name.c_str();
item.type = sqlType;
@@ -860,17 +929,27 @@
item.length = sqlLen;
item.scale = sqlScale;
item.nullable = (*j)->prm_nullable;
+ item.finished = true;
}
}
+ LocalStatus status;
+
+ RefPtr<IMetadataBuilder> inBuilder(metadata->inputParameters->getBuilder(&status));
+ inBuilder->release();
+ status.check();
+
+ RefPtr<IMetadataBuilder> outBuilder(metadata->outputParameters->getBuilder(&status));
+ outBuilder->release();
+ status.check();
+
ExternalProcedure* externalProcedure;
{ // scope
Attachment::Checkout attCout(tdbb->getAttachment(), FB_FUNCTION);
- LocalStatus status;
externalProcedure = attInfo->engine->makeProcedure(&status, attInfo->context, metadata,
- inMsg, outMsg);
+ inBuilder, outBuilder);
status.check();
if (!externalProcedure)
@@ -879,12 +958,21 @@
Arg::Gds(isc_eem_proc_not_returned) <<
prc->getName().toString() << engine);
}
+
+ metadata->inputParameters = inBuilder->getMetadata(&status);
+ status.check();
+
+ metadata->outputParameters = outBuilder->getMetadata(&status);
+ status.check();
}
try
{
- return FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine, metadata.release(),
- externalProcedure, prc);
+ prc->setInputFormat(createFormat(pool, metadata->inputParameters));
+ prc->setOutputFormat(createFormat(pool, metadata->outputParameters));
+
+ prc->setExternal(FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine,
+ metadata.release(), externalProcedure, prc));
}
catch (...)
{
@@ -920,8 +1008,10 @@
if (relation)
{
metadata->triggerTable = relation->rel_name;
- metadata->triggerFields = new MsgMetadata;
+ MsgMetadata* fieldsMsg = new MsgMetadata;
+ metadata->triggerFields = fieldsMsg;
+
Format* relFormat = relation->rel_current_format;
for (size_t i = 0; i < relation->rel_fields->count(); ++i)
@@ -933,7 +1023,7 @@
SLONG sqlLen, sqlSubType, sqlScale, sqlType;
relFormat->fmt_desc[i].getSqlInfo(&sqlLen, &sqlSubType, &sqlScale, &sqlType);
- StatementMetadata::Parameters::Item& item = metadata->triggerFields->items.add();
+ StatementMetadata::Parameters::Item& item = fieldsMsg->items.add();
item.field = field->fld_name.c_str();
item.type = sqlType;
item.subType = sqlSubType;
Modified: firebird/trunk/src/jrd/ExtEngineManager.h
===================================================================
--- firebird/trunk/src/jrd/ExtEngineManager.h 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/jrd/ExtEngineManager.h 2013-03-04 01:42:58 UTC (rev 57719)
@@ -52,29 +52,6 @@
struct record_param;
-class RoutineMessage :
- public Firebird::VersionedIface<Firebird::IRoutineMessage, FB_ROUTINE_MESSAGE_VERSION>,
- public Firebird::PermanentStorage
-{
-public:
- explicit RoutineMessage(MemoryPool& pool)
- : PermanentStorage(pool),
- blr(pool),
- bufferLength(0)
- {
- }
-
- virtual void FB_CARG set(const unsigned char* aBlr, unsigned aBlrLength, unsigned aBufferLength)
- {
- blr.assign(aBlr, aBlrLength);
- bufferLength = aBufferLength;
- }
-
-public:
- Firebird::Array<UCHAR> blr;
- unsigned bufferLength;
-};
-
class TriggerMessage :
public Firebird::VersionedIface<Firebird::ITriggerMessage, FB_TRIGGER_MESSAGE_VERSION>,
public Firebird::PermanentStorage
@@ -180,9 +157,9 @@
Firebird::MetaName name;
Firebird::string entryPoint;
Firebird::string body;
- Firebird::RefPtr<Firebird::MsgMetadata> inputParameters;
- Firebird::RefPtr<Firebird::MsgMetadata> outputParameters;
- Firebird::RefPtr<Firebird::MsgMetadata> triggerFields;
+ Firebird::RefPtr<Firebird::IMessageMetadata> inputParameters;
+ Firebird::RefPtr<Firebird::IMessageMetadata> outputParameters;
+ Firebird::RefPtr<Firebird::IMessageMetadata> triggerFields;
Firebird::MetaName triggerTable;
Firebird::ExternalTrigger::Type triggerType;
@@ -363,12 +340,12 @@
public:
void closeAttachment(thread_db* tdbb, Attachment* attachment);
- Function* makeFunction(thread_db* tdbb, const Jrd::Function* udf,
+ void makeFunction(thread_db* tdbb, Jrd::Function* udf,
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
- const Firebird::string& body, RoutineMessage* inMsg, RoutineMessage* outMsg);
- Procedure* makeProcedure(thread_db* tdbb, const jrd_prc* prc,
+ const Firebird::string& body);
+ void makeProcedure(thread_db* tdbb, jrd_prc* prc,
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
- const Firebird::string& body, RoutineMessage* inMsg, RoutineMessage* outMsg);
+ const Firebird::string& body);
Trigger* makeTrigger(thread_db* tdbb, const Jrd::Trigger* trg,
const Firebird::MetaName& engine, const Firebird::string& entryPoint,
const Firebird::string& body, Firebird::ExternalTrigger::Type type);
Modified: firebird/trunk/src/jrd/Function.epp
===================================================================
--- firebird/trunk/src/jrd/Function.epp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/jrd/Function.epp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -374,9 +374,6 @@
function->fun_external = NULL;
function->setStatement(NULL);
- RoutineMessage inMsg(*attachment->att_pool);
- RoutineMessage outMsg(*attachment->att_pool);
-
if (!X.RDB$ENGINE_NAME.NULL || !X.RDB$FUNCTION_BLR.NULL)
{
if (!X.RDB$ENGINE_NAME.NULL)
@@ -393,46 +390,42 @@
else
body.getBuffer(1)[0] = 0;
- function->fun_external =
- dbb->dbb_extManager.makeFunction(tdbb, function, X.RDB$ENGINE_NAME,
- (X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin(),
- &inMsg, &outMsg);
+ dbb->dbb_extManager.makeFunction(tdbb, function, X.RDB$ENGINE_NAME,
+ (X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin());
if (!function->fun_external)
function->setDefined(false);
}
-
- MemoryPool* const csb_pool = attachment->createPool();
- Jrd::ContextPoolHolder context(tdbb, csb_pool);
-
- try
+ else
{
- AutoPtr<CompilerScratch> csb(CompilerScratch::newCsb(*csb_pool, 5));
+ MemoryPool* const csb_pool = attachment->createPool();
+ Jrd::ContextPoolHolder context(tdbb, csb_pool);
- if (X.RDB$ENGINE_NAME.NULL && !X.RDB$DEBUG_INFO.NULL)
- DBG_parse_debug_info(tdbb, &X.RDB$DEBUG_INFO, *csb->csb_dbg_info);
-
try
{
- MET_parse_routine_blr(tdbb, function, &X.RDB$FUNCTION_BLR, csb,
- !X.RDB$ENGINE_NAME.NULL, inMsg, outMsg);
+ AutoPtr<CompilerScratch> csb(CompilerScratch::newCsb(*csb_pool, 5));
+
+ if (!X.RDB$DEBUG_INFO.NULL)
+ DBG_parse_debug_info(tdbb, &X.RDB$DEBUG_INFO, *csb->csb_dbg_info);
+
+ try
+ {
+ MET_parse_routine_blr(tdbb, function, &X.RDB$FUNCTION_BLR, csb);
+ }
+ catch (const Exception&)
+ {
+ const string name = function->getName().toString();
+ status_exception::raise(Arg::Gds(isc_bad_fun_BLR) << Arg::Str(name));
+ }
}
catch (const Exception&)
{
- if (!X.RDB$ENGINE_NAME.NULL)
- throw;
+ attachment->deletePool(csb_pool);
+ throw;
+ }
- const string name = function->getName().toString();
- status_exception::raise(Arg::Gds(isc_bad_fun_BLR) << Arg::Str(name));
- }
+ function->getStatement()->function = function;
}
- catch (const Exception&)
- {
- attachment->deletePool(csb_pool);
- throw;
- }
-
- function->getStatement()->function = function;
}
else if (!X.RDB$MODULE_NAME.NULL && !X.RDB$ENTRYPOINT.NULL)
{
Modified: firebird/trunk/src/jrd/cmp.cpp
===================================================================
--- firebird/trunk/src/jrd/cmp.cpp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/jrd/cmp.cpp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -262,7 +262,7 @@
}
else if (tail->csb_procedure)
{
- tail->csb_format = tail->csb_procedure->prc_format;
+ tail->csb_format = tail->csb_procedure->prc_record_format;
}
else
{
Modified: firebird/trunk/src/jrd/dfw.epp
===================================================================
--- firebird/trunk/src/jrd/dfw.epp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/jrd/dfw.epp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -5651,10 +5651,7 @@
try
{
- RoutineMessage dummy(*csb_pool);
- MET_parse_routine_blr(tdbb, function, &FUN.RDB$FUNCTION_BLR, csb, false,
- dummy, dummy);
-
+ MET_parse_routine_blr(tdbb, function, &FUN.RDB$FUNCTION_BLR, csb);
valid_blr = true;
}
catch (const Firebird::Exception&)
Modified: firebird/trunk/src/jrd/exe.cpp
===================================================================
--- firebird/trunk/src/jrd/exe.cpp 2013-03-02 02:02:11 UTC (rev 57718)
+++ firebird/trunk/src/jrd/exe.cpp 2013-03-04 01:42:58 UTC (rev 57719)
@@ -191,7 +191,6 @@
fb_sqlstate(sqlstate, status);
}
-static void execute_ext_procedure(thread_db* tdbb, jrd_req* request);
static void execute_looper(thread_db*, jrd_req*, jrd_tra*, const StmtNode*, jrd_req::req_s);
static void looper_seh(thread_db*, jrd_req*, const StmtNode*);
static void release_blobs(thread_db*, jrd_req*);
@@ -626,20 +625,12 @@
{
const JrdStatement* statement = request->getStatement();
- const bool external =
- (statement->procedure && statement->procedure->getExternal()) ||
- (statement->function && statement->function->fun_external);
- if (external)
+ if (StmtNode::is<StallNode>(request->req_message))
execute_looper(tdbb, request, transaction, request->req_next, jrd_req::req_sync);
- else
- {
- if (StmtNode::is<StallNode>(request->req_message))
- execute_looper(tdbb, request, transaction, request->req_next, jrd_req::req_sync);
- if (!(request->req_flags & req_active) || request->req_operation != jrd_req::req_send)
- ERR_post(Arg::Gds(isc_req_sync));
- }
+ if (!(request->req_flags & req_active) || request->req_operation != jrd_req::req_send)
+ ERR_post(Arg::Gds(isc_req_sync));
const MessageNode* message = StmtNode::as<MessageNode>(request->req_message);
const Format* format = message->format;
@@ -679,8 +670,7 @@
}
}
- if (!external)
- execute_looper(tdbb, request, transaction, request->req_next, jrd_req::req_proceed);
+ execute_looper(tdbb, request, transaction, request->req_next, jrd_req::req_proceed);
} //try
catch (const Firebird::Exception&)
@@ -762,43 +752,28 @@
jrd_tra* transaction = request->req_transaction;
const JrdStatement* statement = request->getStatement();
- const bool external =
- (statement->procedure && statement->procedure->getExternal()) ||
- (statement->function && statement->function->fun_external);
+ const SelectNode* selectNode;
- if (external)
+ if (StmtNode::is<MessageNode>(node))
+ message = node;
+ else if ((selectNode = StmtNode::as<SelectNode>(node)))
{
- const CompoundStmtNode* list = StmtNode::as<CompoundStmtNode>(statement->topNode);
- fb_assert(list);
+ const NestConst<StmtNode>* ptr = selectNode->statements.begin();
- message = list->statements[e_extrout_input_message]->as<MessageNode>();
- fb_assert(message);
- }
- else
- {
- const SelectNode* selectNode;
-
- if (StmtNode::is<MessageNode>(node))
- message = node;
- else if ((selectNode = StmtNode::as<SelectNode>(node)))
+ for (const NestConst<StmtNode>* end = selectNode->statements.end(); ptr != end; ++ptr)
{
- const NestConst<StmtNode>* ptr = selectNode->statements.begin();
+ const ReceiveNode* receiveNode = (*ptr)->as<ReceiveNode>();
+ message = receiveNode->message;
- for (const NestConst<St...
[truncated message content] |