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] |