From b17a729ab2940c76f855abd7b5909344f29e72d7 Mon Sep 17 00:00:00 2001 From: Ilya Eremin Date: Thu, 20 Jul 2017 17:03:34 +0300 Subject: [PATCH] Conversion of statements, procedures and functions parameters (CHAR and VARCHAR) to UTF8 in trace log (#95) (#100) * Conversion of statements, procedures and functions parameters (CHAR and VARCHAR) to UTF8 in trace log * cloop interface version check is added for getTextUTF8 function --- src/include/firebird/FirebirdInterface.idl | 3 ++ src/include/firebird/IdlFbInterfaces.h | 34 +++++++++++++- src/jrd/trace/TraceObjects.cpp | 54 ++++++++++++++++++++++ src/jrd/trace/TraceObjects.h | 4 ++ src/utilities/ntrace/TracePluginImpl.cpp | 33 +++++++++++-- 5 files changed, 122 insertions(+), 6 deletions(-) diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index 88759572cd..1d7a8b658e 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -1080,6 +1080,9 @@ interface TraceParams : Versioned { uint getCount(); const dsc* getParam(uint idx); + +version: + const string getTextUTF8(Status status, uint idx); } interface TraceStatement : Versioned diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index 008d64cdcc..007521987c 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -4259,6 +4259,7 @@ namespace Firebird { unsigned (CLOOP_CARG *getCount)(ITraceParams* self) throw(); const dsc* (CLOOP_CARG *getParam)(ITraceParams* self, unsigned idx) throw(); + const char* (CLOOP_CARG *getTextUTF8)(ITraceParams* self, IStatus* status, unsigned idx) throw(); }; protected: @@ -4272,7 +4273,7 @@ namespace Firebird } public: - static const unsigned VERSION = 2; + static const unsigned VERSION = 3; unsigned getCount() { @@ -4285,6 +4286,20 @@ namespace Firebird const dsc* ret = static_cast(this->cloopVTable)->getParam(this, idx); return ret; } + + template const char* getTextUTF8(StatusType* status, unsigned idx) + { + if (cloopVTable->version < 3) + { + StatusType::setVersionError(status, "ITraceParams", cloopVTable->version, 3); + StatusType::checkException(status); + return 0; + } + StatusType::clearException(status); + const char* ret = static_cast(this->cloopVTable)->getTextUTF8(this, status, idx); + StatusType::checkException(status); + return ret; + } }; class ITraceStatement : public IVersioned @@ -14254,6 +14269,7 @@ namespace Firebird this->version = Base::VERSION; this->getCount = &Name::cloopgetCountDispatcher; this->getParam = &Name::cloopgetParamDispatcher; + this->getTextUTF8 = &Name::cloopgetTextUTF8Dispatcher; } } vTable; @@ -14285,6 +14301,21 @@ namespace Firebird return static_cast(0); } } + + static const char* CLOOP_CARG cloopgetTextUTF8Dispatcher(ITraceParams* self, IStatus* status, unsigned idx) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::getTextUTF8(&status2, idx); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } }; template > > @@ -14302,6 +14333,7 @@ namespace Firebird virtual unsigned getCount() = 0; virtual const dsc* getParam(unsigned idx) = 0; + virtual const char* getTextUTF8(StatusType* status, unsigned idx) = 0; }; template diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index 3a4e289c6b..76aa32a9f1 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -280,6 +280,33 @@ const dsc* TraceSQLStatementImpl::DSQLParamsImpl::getParam(FB_SIZE_T idx) return NULL; } +const char* TraceSQLStatementImpl::DSQLParamsImpl::getTextUTF8(CheckStatusWrapper* status, FB_SIZE_T idx) +{ + const dsc* param = getParam(idx); + UCHAR* address; + + switch (param->dsc_dtype) + { + case dtype_text: + address = param->dsc_address; + break; + + case dtype_varying: + address = param->dsc_address + sizeof(USHORT); + break; + + default: + return NULL; + } + + string src(address); + + if (DataTypeUtil::convertToUTF8(src, temp_utf8_text, param->dsc_sub_type)) + return temp_utf8_text.c_str(); + else + return (const char*)address; +} + /// TraceFailedSQLStatement @@ -307,6 +334,33 @@ const dsc* TraceParamsImpl::getParam(FB_SIZE_T idx) return m_descs->getParam(idx); } +const char* TraceParamsImpl::getTextUTF8(CheckStatusWrapper* status, FB_SIZE_T idx) +{ + const dsc* param = getParam(idx); + UCHAR* address; + + switch (param->dsc_dtype) + { + case dtype_text: + address = param->dsc_address; + break; + + case dtype_varying: + address = param->dsc_address + sizeof(USHORT); + break; + + default: + return NULL; + } + + string src(address); + + if (DataTypeUtil::convertToUTF8(src, temp_utf8_text, param->dsc_sub_type)) + return temp_utf8_text.c_str(); + else + return (const char*)address; +} + /// TraceDscFromValues diff --git a/src/jrd/trace/TraceObjects.h b/src/jrd/trace/TraceObjects.h index 5bfce6c3b7..1a886a9932 100644 --- a/src/jrd/trace/TraceObjects.h +++ b/src/jrd/trace/TraceObjects.h @@ -206,6 +206,7 @@ private: FB_SIZE_T getCount(); const dsc* getParam(FB_SIZE_T idx); + const char* getTextUTF8(Firebird::CheckStatusWrapper* status, FB_SIZE_T idx); private: void fillParams(); @@ -213,6 +214,7 @@ private: const dsql_req* const m_stmt; const Firebird::Array* m_params; Firebird::HalfStaticArray m_descs; + Firebird::string temp_utf8_text; }; void fillPlan(bool explained); @@ -285,9 +287,11 @@ public: // TraceParams implementation FB_SIZE_T getCount(); const dsc* getParam(FB_SIZE_T idx); + const char* getTextUTF8(Firebird::CheckStatusWrapper* status, FB_SIZE_T idx); private: TraceDescriptors* m_descs; + Firebird::string temp_utf8_text; }; diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index 82fdb79cbf..e821b3cb33 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -46,6 +46,7 @@ #include "../../dsql/sqlda_pub.h" #include "../../common/classes/ImplementHelper.h" #include "../../common/SimpleStatusVector.h" +#include "../../jrd/status.h" using namespace Firebird; using namespace Jrd; @@ -789,19 +790,41 @@ void TracePluginImpl::appendParams(ITraceParams* params) { // Handle potentially long string values case dtype_text: - formatStringArgument(paramvalue, - parameters->dsc_address, parameters->dsc_length); + { + FbLocalStatus status; + const char* text = params->getTextUTF8(&status, i); + + if (status->getState() & IStatus::STATE_ERRORS) + { + formatStringArgument(paramvalue, + parameters->dsc_address, parameters->dsc_length); + } + else + formatStringArgument(paramvalue, (UCHAR*)text, strlen(text)); + break; + } case dtype_cstring: formatStringArgument(paramvalue, parameters->dsc_address, strlen(reinterpret_cast(parameters->dsc_address))); break; case dtype_varying: - formatStringArgument(paramvalue, - parameters->dsc_address + 2, - *(USHORT*)parameters->dsc_address); + { + FbLocalStatus status; + const char* text = params->getTextUTF8(&status, i); + + if (status->getState() & IStatus::STATE_ERRORS) + { + formatStringArgument(paramvalue, + parameters->dsc_address + 2, + *(USHORT*)parameters->dsc_address); + } + else + formatStringArgument(paramvalue, (UCHAR*)text, strlen(text)); + break; + } // Handle quad case dtype_quad: