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;