From 6c2e26cbbd3c9d64a93b3c5284135be4508aec81 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Mon, 17 Oct 2016 13:03:24 -0200 Subject: [PATCH] Fixed CORE-5314 - UDFs declared with large varchars take excessive time to execute. --- src/dsql/ExprNodes.cpp | 13 ++++++++++--- src/dsql/ExprNodes.h | 7 +++++++ src/jrd/fun.epp | 3 +-- src/jrd/fun_proto.h | 2 +- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index c023688097..83efb03a41 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -11260,7 +11260,7 @@ ValueExprNode* UdfCallNode::pass2(thread_db* tdbb, CompilerScratch* csb) dsc desc; getDesc(tdbb, csb, &desc); - impureOffset = CMP_impure(csb, sizeof(impure_value)); + impureOffset = CMP_impure(csb, sizeof(Impure)); if (function->isDefined() && !function->fun_entrypoint) { @@ -11282,7 +11282,8 @@ ValueExprNode* UdfCallNode::pass2(thread_db* tdbb, CompilerScratch* csb) dsc* UdfCallNode::execute(thread_db* tdbb, jrd_req* request) const { UCHAR* impure = request->getImpure(impureOffset); - impure_value* value = request->getImpure(impureOffset); + Impure* impureArea = request->getImpure(impureOffset); + impure_value* value = &impureArea->value; USHORT& invariantFlags = value->vlu_flags; @@ -11347,7 +11348,13 @@ dsc* UdfCallNode::execute(thread_db* tdbb, jrd_req* request) const else value->vlu_desc.dsc_address = (UCHAR*) &value->vlu_misc; - FUN_evaluate(tdbb, function, args->items, value); + if (!impureArea->temp) + { + impureArea->temp = + FB_NEW_POOL(*tdbb->getDefaultPool()) Array(*tdbb->getDefaultPool()); + } + + FUN_evaluate(tdbb, function, args->items, value, *impureArea->temp); } else { diff --git a/src/dsql/ExprNodes.h b/src/dsql/ExprNodes.h index 2b8b222c07..a557aa54da 100644 --- a/src/dsql/ExprNodes.h +++ b/src/dsql/ExprNodes.h @@ -1681,6 +1681,13 @@ public: class UdfCallNode : public TypedNode { +private: + struct Impure + { + impure_value value; // must be first + Firebird::Array* temp; + }; + public: explicit UdfCallNode(MemoryPool& pool, const Firebird::QualifiedName& aName, ValueListNode* aArgs = NULL); diff --git a/src/jrd/fun.epp b/src/jrd/fun.epp index d9ded9b2bb..2efedbacb1 100644 --- a/src/jrd/fun.epp +++ b/src/jrd/fun.epp @@ -303,7 +303,7 @@ static bool private_move(Jrd::thread_db* tdbb, dsc* from, dsc* to); void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArray& node, - impure_value* value) + impure_value* value, Array& temp) { /************************************** * @@ -370,7 +370,6 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra try { UDF_ARG args[MAX_UDF_ARGUMENTS + 1]; - HalfStaticArray temp; // Start by constructing argument list UCHAR* temp_ptr = temp.getBuffer(function->fun_temp_length + FB_DOUBLE_ALIGN); diff --git a/src/jrd/fun_proto.h b/src/jrd/fun_proto.h index 29411694c1..b32cc0503c 100644 --- a/src/jrd/fun_proto.h +++ b/src/jrd/fun_proto.h @@ -37,7 +37,7 @@ public: }; void FUN_evaluate(Jrd::thread_db*, const Jrd::Function*, const Jrd::NestValueArray&, - Jrd::impure_value*); + Jrd::impure_value*, Firebird::Array& temp); #endif // JRD_FUN_PROTO_H