diff --git a/doc/Using_OO_API.md b/doc/Using_OO_API.md index 02b9821ed3c..4347c488fc4 100644 --- a/doc/Using_OO_API.md +++ b/doc/Using_OO_API.md @@ -1744,6 +1744,10 @@ completed at the moment when given timer should alarm. - void decodeTimeStampTzEx(Status status, const ISC_TIMESTAMP_TZ_EX* timeStampTz, uint* year, uint* month, uint* day, uint* hours, uint* minutes, uint* seconds, uint* fractions, uint timeZoneBufferLength, string timeZoneBuffer) – decode timestamp taking extended time zone into an account. +- Attachment executeCreateDatabase2(Status status, uint stmtLength, const string creatDBstatement, uint dialect, + uint dpbLength, const uchar* dpb, boolean* stmtIsCreateDb); +- void convert(Status status, uint sourceType, uint sourceScale, uint sourceLength, const void* source, + uint targetType, uint targetScale, uint targetLength, void* target); XpbBuilder methods: diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index 8815fbabba2..06601ffa6ef 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -1263,6 +1263,10 @@ version: // 5.0 => 6.0 Alpha1 uint stmtLength, const string creatDBstatement, uint dialect, uint dpbLength, const uchar* dpb, boolean* stmtIsCreateDb); + +version: // 5.0 => 6.0 Alpha1 + void convert(Status status, uint sourceType, uint sourceScale, uint sourceLength, const void* source, + uint targetType, uint targetScale, uint targetLength, void* target); } interface OffsetsCallback : Versioned diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index 0da59e7f052..43f3041054d 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -4815,7 +4815,7 @@ namespace Firebird } }; -#define FIREBIRD_IUTIL_VERSION 5u +#define FIREBIRD_IUTIL_VERSION 6u class IUtil : public IVersioned { @@ -4845,6 +4845,7 @@ namespace Firebird void (CLOOP_CARG *decodeTimeTzEx)(IUtil* self, IStatus* status, const ISC_TIME_TZ_EX* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) CLOOP_NOEXCEPT; void (CLOOP_CARG *decodeTimeStampTzEx)(IUtil* self, IStatus* status, const ISC_TIMESTAMP_TZ_EX* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) CLOOP_NOEXCEPT; IAttachment* (CLOOP_CARG *executeCreateDatabase2)(IUtil* self, IStatus* status, unsigned stmtLength, const char* creatDBstatement, unsigned dialect, unsigned dpbLength, const unsigned char* dpb, FB_BOOLEAN* stmtIsCreateDb) CLOOP_NOEXCEPT; + void (CLOOP_CARG *convert)(IUtil* self, IStatus* status, unsigned sourceType, unsigned sourceScale, unsigned sourceLength, const void* source, unsigned targetType, unsigned targetScale, unsigned targetLength, void* target) CLOOP_NOEXCEPT; }; protected: @@ -5079,6 +5080,19 @@ namespace Firebird StatusType::checkException(status); return ret; } + + template void convert(StatusType* status, unsigned sourceType, unsigned sourceScale, unsigned sourceLength, const void* source, unsigned targetType, unsigned targetScale, unsigned targetLength, void* target) + { + if (cloopVTable->version < 6) + { + StatusType::setVersionError(status, "IUtil", cloopVTable->version, 6); + StatusType::checkException(status); + return; + } + StatusType::clearException(status); + static_cast(this->cloopVTable)->convert(this, status, sourceType, sourceScale, sourceLength, source, targetType, targetScale, targetLength, target); + StatusType::checkException(status); + } }; #define FIREBIRD_IOFFSETS_CALLBACK_VERSION 2u @@ -16430,6 +16444,7 @@ namespace Firebird this->decodeTimeTzEx = &Name::cloopdecodeTimeTzExDispatcher; this->decodeTimeStampTzEx = &Name::cloopdecodeTimeStampTzExDispatcher; this->executeCreateDatabase2 = &Name::cloopexecuteCreateDatabase2Dispatcher; + this->convert = &Name::cloopconvertDispatcher; } } vTable; @@ -16756,6 +16771,20 @@ namespace Firebird return static_cast(0); } } + + static void CLOOP_CARG cloopconvertDispatcher(IUtil* self, IStatus* status, unsigned sourceType, unsigned sourceScale, unsigned sourceLength, const void* source, unsigned targetType, unsigned targetScale, unsigned targetLength, void* target) CLOOP_NOEXCEPT + { + StatusType status2(status); + + try + { + static_cast(self)->Name::convert(&status2, sourceType, sourceScale, sourceLength, source, targetType, targetScale, targetLength, target); + } + catch (...) + { + StatusType::catchException(&status2); + } + } }; template > > @@ -16794,6 +16823,7 @@ namespace Firebird virtual void decodeTimeTzEx(StatusType* status, const ISC_TIME_TZ_EX* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) = 0; virtual void decodeTimeStampTzEx(StatusType* status, const ISC_TIMESTAMP_TZ_EX* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) = 0; virtual IAttachment* executeCreateDatabase2(StatusType* status, unsigned stmtLength, const char* creatDBstatement, unsigned dialect, unsigned dpbLength, const unsigned char* dpb, FB_BOOLEAN* stmtIsCreateDb) = 0; + virtual void convert(StatusType* status, unsigned sourceType, unsigned sourceScale, unsigned sourceLength, const void* source, unsigned targetType, unsigned targetScale, unsigned targetLength, void* target) = 0; }; template diff --git a/src/include/gen/Firebird.pas b/src/include/gen/Firebird.pas index 0bef5dea26a..15fb8074f2c 100644 --- a/src/include/gen/Firebird.pas +++ b/src/include/gen/Firebird.pas @@ -571,6 +571,7 @@ ISC_TIMESTAMP_TZ_EX = record IUtil_decodeTimeTzExPtr = procedure(this: IUtil; status: IStatus; timeTz: ISC_TIME_TZ_EXPtr; hours: CardinalPtr; minutes: CardinalPtr; seconds: CardinalPtr; fractions: CardinalPtr; timeZoneBufferLength: Cardinal; timeZoneBuffer: PAnsiChar); cdecl; IUtil_decodeTimeStampTzExPtr = procedure(this: IUtil; status: IStatus; timeStampTz: ISC_TIMESTAMP_TZ_EXPtr; year: CardinalPtr; month: CardinalPtr; day: CardinalPtr; hours: CardinalPtr; minutes: CardinalPtr; seconds: CardinalPtr; fractions: CardinalPtr; timeZoneBufferLength: Cardinal; timeZoneBuffer: PAnsiChar); cdecl; IUtil_executeCreateDatabase2Ptr = function(this: IUtil; status: IStatus; stmtLength: Cardinal; creatDBstatement: PAnsiChar; dialect: Cardinal; dpbLength: Cardinal; dpb: BytePtr; stmtIsCreateDb: BooleanPtr): IAttachment; cdecl; + IUtil_convertPtr = procedure(this: IUtil; status: IStatus; sourceType: Cardinal; sourceScale: Cardinal; sourceLength: Cardinal; source: Pointer; targetType: Cardinal; targetScale: Cardinal; targetLength: Cardinal; target: Pointer); cdecl; IOffsetsCallback_setOffsetPtr = procedure(this: IOffsetsCallback; status: IStatus; index: Cardinal; offset: Cardinal; nullOffset: Cardinal); cdecl; IXpbBuilder_clearPtr = procedure(this: IXpbBuilder; status: IStatus); cdecl; IXpbBuilder_removeCurrentPtr = procedure(this: IXpbBuilder; status: IStatus); cdecl; @@ -2811,10 +2812,11 @@ UtilVTable = class(VersionedVTable) decodeTimeTzEx: IUtil_decodeTimeTzExPtr; decodeTimeStampTzEx: IUtil_decodeTimeStampTzExPtr; executeCreateDatabase2: IUtil_executeCreateDatabase2Ptr; + convert: IUtil_convertPtr; end; IUtil = class(IVersioned) - const VERSION = 5; + const VERSION = 6; procedure getFbVersion(status: IStatus; att: IAttachment; callback: IVersionCallback); procedure loadBlob(status: IStatus; blobId: ISC_QUADPtr; att: IAttachment; tra: ITransaction; file_: PAnsiChar; txt: Boolean); @@ -2839,6 +2841,7 @@ IUtil = class(IVersioned) procedure decodeTimeTzEx(status: IStatus; timeTz: ISC_TIME_TZ_EXPtr; hours: CardinalPtr; minutes: CardinalPtr; seconds: CardinalPtr; fractions: CardinalPtr; timeZoneBufferLength: Cardinal; timeZoneBuffer: PAnsiChar); procedure decodeTimeStampTzEx(status: IStatus; timeStampTz: ISC_TIMESTAMP_TZ_EXPtr; year: CardinalPtr; month: CardinalPtr; day: CardinalPtr; hours: CardinalPtr; minutes: CardinalPtr; seconds: CardinalPtr; fractions: CardinalPtr; timeZoneBufferLength: Cardinal; timeZoneBuffer: PAnsiChar); function executeCreateDatabase2(status: IStatus; stmtLength: Cardinal; creatDBstatement: PAnsiChar; dialect: Cardinal; dpbLength: Cardinal; dpb: BytePtr; stmtIsCreateDb: BooleanPtr): IAttachment; + procedure convert(status: IStatus; sourceType: Cardinal; sourceScale: Cardinal; sourceLength: Cardinal; source: Pointer; targetType: Cardinal; targetScale: Cardinal; targetLength: Cardinal; target: Pointer); end; IUtilImpl = class(IUtil) @@ -2867,6 +2870,7 @@ IUtilImpl = class(IUtil) procedure decodeTimeTzEx(status: IStatus; timeTz: ISC_TIME_TZ_EXPtr; hours: CardinalPtr; minutes: CardinalPtr; seconds: CardinalPtr; fractions: CardinalPtr; timeZoneBufferLength: Cardinal; timeZoneBuffer: PAnsiChar); virtual; abstract; procedure decodeTimeStampTzEx(status: IStatus; timeStampTz: ISC_TIMESTAMP_TZ_EXPtr; year: CardinalPtr; month: CardinalPtr; day: CardinalPtr; hours: CardinalPtr; minutes: CardinalPtr; seconds: CardinalPtr; fractions: CardinalPtr; timeZoneBufferLength: Cardinal; timeZoneBuffer: PAnsiChar); virtual; abstract; function executeCreateDatabase2(status: IStatus; stmtLength: Cardinal; creatDBstatement: PAnsiChar; dialect: Cardinal; dpbLength: Cardinal; dpb: BytePtr; stmtIsCreateDb: BooleanPtr): IAttachment; virtual; abstract; + procedure convert(status: IStatus; sourceType: Cardinal; sourceScale: Cardinal; sourceLength: Cardinal; source: Pointer; targetType: Cardinal; targetScale: Cardinal; targetLength: Cardinal; target: Pointer); virtual; abstract; end; OffsetsCallbackVTable = class(VersionedVTable) @@ -8855,6 +8859,17 @@ function IUtil.executeCreateDatabase2(status: IStatus; stmtLength: Cardinal; cre FbException.checkException(status); end; +procedure IUtil.convert(status: IStatus; sourceType: Cardinal; sourceScale: Cardinal; sourceLength: Cardinal; source: Pointer; targetType: Cardinal; targetScale: Cardinal; targetLength: Cardinal; target: Pointer); +begin + if (vTable.version < 6) then begin + FbException.setVersionError(status, 'IUtil', vTable.version, 6); + end + else begin + UtilVTable(vTable).convert(Self, status, sourceType, sourceScale, sourceLength, source, targetType, targetScale, targetLength, target); + end; + FbException.checkException(status); +end; + procedure IOffsetsCallback.setOffset(status: IStatus; index: Cardinal; offset: Cardinal; nullOffset: Cardinal); begin OffsetsCallbackVTable(vTable).setOffset(Self, status, index, offset, nullOffset); @@ -14881,6 +14896,15 @@ function IUtilImpl_executeCreateDatabase2Dispatcher(this: IUtil; status: IStatus end end; +procedure IUtilImpl_convertDispatcher(this: IUtil; status: IStatus; sourceType: Cardinal; sourceScale: Cardinal; sourceLength: Cardinal; source: Pointer; targetType: Cardinal; targetScale: Cardinal; targetLength: Cardinal; target: Pointer); cdecl; +begin + try + IUtilImpl(this).convert(status, sourceType, sourceScale, sourceLength, source, targetType, targetScale, targetLength, target); + except + on e: Exception do FbException.catchException(status, e); + end +end; + var IUtilImpl_vTable: UtilVTable; @@ -18199,7 +18223,7 @@ initialization IVersionCallbackImpl_vTable.callback := @IVersionCallbackImpl_callbackDispatcher; IUtilImpl_vTable := UtilVTable.create; - IUtilImpl_vTable.version := 5; + IUtilImpl_vTable.version := 6; IUtilImpl_vTable.getFbVersion := @IUtilImpl_getFbVersionDispatcher; IUtilImpl_vTable.loadBlob := @IUtilImpl_loadBlobDispatcher; IUtilImpl_vTable.dumpBlob := @IUtilImpl_dumpBlobDispatcher; @@ -18223,6 +18247,7 @@ initialization IUtilImpl_vTable.decodeTimeTzEx := @IUtilImpl_decodeTimeTzExDispatcher; IUtilImpl_vTable.decodeTimeStampTzEx := @IUtilImpl_decodeTimeStampTzExDispatcher; IUtilImpl_vTable.executeCreateDatabase2 := @IUtilImpl_executeCreateDatabase2Dispatcher; + IUtilImpl_vTable.convert := @IUtilImpl_convertDispatcher; IOffsetsCallbackImpl_vTable := OffsetsCallbackVTable.create; IOffsetsCallbackImpl_vTable.version := 2; diff --git a/src/yvalve/YObjects.h b/src/yvalve/YObjects.h index 057012bc8be..22ef7feed48 100644 --- a/src/yvalve/YObjects.h +++ b/src/yvalve/YObjects.h @@ -737,6 +737,11 @@ class UtilInterface final : void decodeTimeStampTzEx(Firebird::CheckStatusWrapper* status, const ISC_TIMESTAMP_TZ_EX* timeStampEx, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) override; + + void convert(Firebird::CheckStatusWrapper* status, + unsigned sourceType, unsigned sourceScale, unsigned sourceLength, const void* source, + unsigned targetType, unsigned targetScale, unsigned targetLength, void* target) override; + }; } // namespace Why diff --git a/src/yvalve/utl.cpp b/src/yvalve/utl.cpp index 1caead1b0e9..2f14933d3c1 100644 --- a/src/yvalve/utl.cpp +++ b/src/yvalve/utl.cpp @@ -798,6 +798,43 @@ void UtilInterface::encodeTimeStampTz(CheckStatusWrapper* status, ISC_TIMESTAMP_ } } +void UtilInterface::convert(Firebird::CheckStatusWrapper* status, + unsigned sourceType, unsigned sourceScale, unsigned sourceLength, const void* source, + unsigned targetType, unsigned targetScale, unsigned targetLength, void* target) +{ + dsc sourceDesc; + memset(&sourceDesc, 0, sizeof(sourceDesc)); + sourceDesc.dsc_dtype = fb_utils::sqlTypeToDscType(sourceType); + sourceDesc.dsc_scale = sourceScale; + sourceDesc.dsc_length = sourceLength; + if (sourceDesc.isText()) + sourceDesc.setTextType(CS_dynamic); + sourceDesc.dsc_address = (UCHAR*) source; + + dsc targetDesc; + memset(&targetDesc, 0, sizeof(targetDesc)); + targetDesc.dsc_dtype = fb_utils::sqlTypeToDscType(targetType); + targetDesc.dsc_scale = targetScale; + targetDesc.dsc_length = targetLength; + if (targetDesc.isText()) + targetDesc.setTextType(CS_dynamic); + targetDesc.dsc_address = static_cast(target); + + try + { + CVT_move(&sourceDesc, &targetDesc, 0, + [](const Arg::StatusVector& status) + { + status.raise(); + } + ); + } + catch (const Exception& ex) + { + ex.stuffException(status); + } +} + ISC_DATE UtilInterface::encodeDate(unsigned year, unsigned month, unsigned day) { tm times;