8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 21:23:04 +01:00

Enhanced support of decimal float numbers in the client: use better names for SQL_ constants, added interfaces supporting access to decimal float fields in native format, use them in isql instead direct library access, added decimal float support in messages and a sample of it

This commit is contained in:
AlexPeshkoff 2017-04-04 13:00:27 +03:00
parent f995ed4408
commit 1b8b7d37f5
16 changed files with 562 additions and 64 deletions

View File

@ -4,6 +4,9 @@
* DESCRIPTION: A sample of using static messages.
* Prints user-defined tables with comments.
*
* Example for the following interface:
* IDecFloat16 - support for IEEE-754 64-bit decimal float numbers
*
* Example for the following macro:
*
* FB_MESSAGE - defines static messages
@ -32,6 +35,7 @@
#include <firebird/Message.h>
static IMaster* master = fb_get_master_interface();
static IDecFloat16* idf = NULL;
int main()
{
@ -51,6 +55,8 @@ int main()
try
{
idf = master->getUtilInterface()->getDecFloat16(&status);
att = prov->attachDatabase(&status, dbName, 0, NULL);
tra = att->startTransaction(&status, 0, NULL);
@ -72,13 +78,15 @@ int main()
(FB_SMALLINT, relationId)
(FB_VARCHAR(31), relationName)
(FB_VARCHAR(100), description)
(FB_DECFLOAT16, df16)
) output(&status, master);
input.clear();
input->systemFlag = 0;
rs = att->openCursor(&status, tra, 0,
"select rdb$relation_id, rdb$relation_name, rdb$description"
"select rdb$relation_id, rdb$relation_name, rdb$description,"
" cast (rdb$relation_id as decfloat(16)) * 0.05 as df16"
" from rdb$relations"
" where rdb$system_flag = ?"
" order by rdb$relation_id",
@ -89,10 +97,13 @@ int main()
{
unsigned lRelName = output->relationNameNull ? 0 : output->relationName.length;
unsigned lDesc = output->descriptionNull ? 0 : output->description.length;
printf("%4d %*.*s%c%*.*s\n", output->relationId,
char t[IDecFloat16::STRING_SIZE];
idf->toStr(&output->df16, t);
printf("%4d %*.*s%c%*.*s (%s)\n", output->relationId,
lRelName, lRelName, output->relationName.str,
lDesc ? '/' : ' ',
lDesc, lDesc, output->description.str);
lDesc, lDesc, output->description.str, t);
}
rs->close(&status);

View File

@ -173,12 +173,12 @@ MetadataFromBlr::MetadataFromBlr(unsigned aBlrLength, const unsigned char* aBlr,
break;
case blr_dec64:
item->type = SQL_DEC64;
item->type = SQL_DEC16;
item->length = sizeof(Decimal64);
break;
case blr_dec128:
item->type = SQL_DEC128;
item->type = SQL_DEC34;
item->length = sizeof(Decimal128);
break;

View File

@ -1338,12 +1338,12 @@ void dsc::getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG
break;
case dtype_dec64:
*sqlType = SQL_DEC64;
*sqlType = SQL_DEC16;
*sqlScale = 0;
break;
case dtype_dec128:
*sqlType = SQL_DEC128;
*sqlType = SQL_DEC34;
*sqlScale = 0;
break;

View File

@ -1516,9 +1516,9 @@ UCHAR sqlTypeToDscType(SSHORT sqlType)
return dtype_quad;
case SQL_BOOLEAN:
return dtype_boolean;
case SQL_DEC64:
case SQL_DEC16:
return dtype_dec64;
case SQL_DEC128:
case SQL_DEC34:
return dtype_dec128;
default:
return dtype_unknown;

View File

@ -78,8 +78,8 @@ typedef struct
#define SQL_TYPE_TIME 560
#define SQL_TYPE_DATE 570
#define SQL_INT64 580
#define SQL_DEC64 32760
#define SQL_DEC128 32762
#define SQL_DEC16 32760
#define SQL_DEC34 32762
#define SQL_BOOLEAN 32764
#define SQL_NULL 32766

View File

@ -29,6 +29,8 @@
typedef ISC_DATE;
typedef ISC_QUAD;
typedef ISC_TIME;
typedef FB_DEC16;
typedef FB_DEC34;
// Versioned interface - base for all FB interfaces
interface Versioned
@ -985,6 +987,8 @@ interface Util : Versioned
version:
EventBlock createEventBlock(Status status, const string* events);
DecFloat16 getDecFloat16(Status status);
DecFloat34 getDecFloat34(Status status);
}
interface OffsetsCallback : Versioned
@ -1365,3 +1369,23 @@ interface UdrPlugin : Versioned
void registerProcedure(Status status, const string name, UdrProcedureFactory factory);
void registerTrigger(Status status, const string name, UdrTriggerFactory factory);
}
interface DecFloat16 : Versioned
{
const uint BCD_SIZE = 16;
const uint STRING_SIZE = 25; // includes terminating \0
void scatter(const FB_DEC16* from, int* sign, uchar* bcd, int* exp);
void toStr(const FB_DEC16* from, string to);
void gather(int sign, const uchar* bcd, int exp, FB_DEC16* to);
void fromStr(Status status, const string from, FB_DEC16* to);
}
interface DecFloat34 : Versioned
{
const uint BCD_SIZE = 34;
const uint STRING_SIZE = 43; // includes terminating \0
void scatter(const FB_DEC34* from, int* sign, uchar* bcd, int* exp);
void toStr(const FB_DEC34* from, string to);
void gather(int sign, const uchar* bcd, int exp, FB_DEC34* to);
void fromStr(Status status, const string from, FB_DEC34* to);
}

View File

@ -111,6 +111,8 @@ namespace Firebird
class IUdrProcedureFactory;
class IUdrTriggerFactory;
class IUdrPlugin;
class IDecFloat16;
class IDecFloat34;
// Interfaces declarations
@ -3695,6 +3697,8 @@ namespace Firebird
IXpbBuilder* (CLOOP_CARG *getXpbBuilder)(IUtil* self, IStatus* status, unsigned kind, const unsigned char* buf, unsigned len) throw();
unsigned (CLOOP_CARG *setOffsets)(IUtil* self, IStatus* status, IMessageMetadata* metadata, IOffsetsCallback* callback) throw();
IEventBlock* (CLOOP_CARG *createEventBlock)(IUtil* self, IStatus* status, const char** events) throw();
IDecFloat16* (CLOOP_CARG *getDecFloat16)(IUtil* self, IStatus* status) throw();
IDecFloat34* (CLOOP_CARG *getDecFloat34)(IUtil* self, IStatus* status) throw();
};
protected:
@ -3809,6 +3813,34 @@ namespace Firebird
StatusType::checkException(status);
return ret;
}
template <typename StatusType> IDecFloat16* getDecFloat16(StatusType* status)
{
if (cloopVTable->version < 3)
{
StatusType::setVersionError(status, "IUtil", cloopVTable->version, 3);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
IDecFloat16* ret = static_cast<VTable*>(this->cloopVTable)->getDecFloat16(this, status);
StatusType::checkException(status);
return ret;
}
template <typename StatusType> IDecFloat34* getDecFloat34(StatusType* status)
{
if (cloopVTable->version < 3)
{
StatusType::setVersionError(status, "IUtil", cloopVTable->version, 3);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
IDecFloat34* ret = static_cast<VTable*>(this->cloopVTable)->getDecFloat34(this, status);
StatusType::checkException(status);
return ret;
}
};
class IOffsetsCallback : public IVersioned
@ -5269,6 +5301,106 @@ namespace Firebird
}
};
class IDecFloat16 : public IVersioned
{
public:
struct VTable : public IVersioned::VTable
{
void (CLOOP_CARG *scatter)(IDecFloat16* self, const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp) throw();
void (CLOOP_CARG *toStr)(IDecFloat16* self, const FB_DEC16* from, char* to) throw();
void (CLOOP_CARG *gather)(IDecFloat16* self, int sign, const unsigned char* bcd, int exp, FB_DEC16* to) throw();
void (CLOOP_CARG *fromStr)(IDecFloat16* self, IStatus* status, const char* from, FB_DEC16* to) throw();
};
protected:
IDecFloat16(DoNotInherit)
: IVersioned(DoNotInherit())
{
}
~IDecFloat16()
{
}
public:
static const unsigned VERSION = 2;
static const unsigned BCD_SIZE = 16;
static const unsigned STRING_SIZE = 25;
void scatter(const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp)
{
static_cast<VTable*>(this->cloopVTable)->scatter(this, from, sign, bcd, exp);
}
void toStr(const FB_DEC16* from, char* to)
{
static_cast<VTable*>(this->cloopVTable)->toStr(this, from, to);
}
void gather(int sign, const unsigned char* bcd, int exp, FB_DEC16* to)
{
static_cast<VTable*>(this->cloopVTable)->gather(this, sign, bcd, exp, to);
}
template <typename StatusType> void fromStr(StatusType* status, const char* from, FB_DEC16* to)
{
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->fromStr(this, status, from, to);
StatusType::checkException(status);
}
};
class IDecFloat34 : public IVersioned
{
public:
struct VTable : public IVersioned::VTable
{
void (CLOOP_CARG *scatter)(IDecFloat34* self, const FB_DEC34* from, int* sign, unsigned char* bcd, int* exp) throw();
void (CLOOP_CARG *toStr)(IDecFloat34* self, const FB_DEC34* from, char* to) throw();
void (CLOOP_CARG *gather)(IDecFloat34* self, int sign, const unsigned char* bcd, int exp, FB_DEC34* to) throw();
void (CLOOP_CARG *fromStr)(IDecFloat34* self, IStatus* status, const char* from, FB_DEC34* to) throw();
};
protected:
IDecFloat34(DoNotInherit)
: IVersioned(DoNotInherit())
{
}
~IDecFloat34()
{
}
public:
static const unsigned VERSION = 2;
static const unsigned BCD_SIZE = 34;
static const unsigned STRING_SIZE = 43;
void scatter(const FB_DEC34* from, int* sign, unsigned char* bcd, int* exp)
{
static_cast<VTable*>(this->cloopVTable)->scatter(this, from, sign, bcd, exp);
}
void toStr(const FB_DEC34* from, char* to)
{
static_cast<VTable*>(this->cloopVTable)->toStr(this, from, to);
}
void gather(int sign, const unsigned char* bcd, int exp, FB_DEC34* to)
{
static_cast<VTable*>(this->cloopVTable)->gather(this, sign, bcd, exp, to);
}
template <typename StatusType> void fromStr(StatusType* status, const char* from, FB_DEC34* to)
{
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->fromStr(this, status, from, to);
StatusType::checkException(status);
}
};
// Interfaces implementations
template <typename Name, typename StatusType, typename Base>
@ -12940,6 +13072,8 @@ namespace Firebird
this->getXpbBuilder = &Name::cloopgetXpbBuilderDispatcher;
this->setOffsets = &Name::cloopsetOffsetsDispatcher;
this->createEventBlock = &Name::cloopcreateEventBlockDispatcher;
this->getDecFloat16 = &Name::cloopgetDecFloat16Dispatcher;
this->getDecFloat34 = &Name::cloopgetDecFloat34Dispatcher;
}
} vTable;
@ -13137,6 +13271,36 @@ namespace Firebird
return static_cast<IEventBlock*>(0);
}
}
static IDecFloat16* CLOOP_CARG cloopgetDecFloat16Dispatcher(IUtil* self, IStatus* status) throw()
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::getDecFloat16(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<IDecFloat16*>(0);
}
}
static IDecFloat34* CLOOP_CARG cloopgetDecFloat34Dispatcher(IUtil* self, IStatus* status) throw()
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::getDecFloat34(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<IDecFloat34*>(0);
}
}
};
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUtil> > >
@ -13166,6 +13330,8 @@ namespace Firebird
virtual IXpbBuilder* getXpbBuilder(StatusType* status, unsigned kind, const unsigned char* buf, unsigned len) = 0;
virtual unsigned setOffsets(StatusType* status, IMessageMetadata* metadata, IOffsetsCallback* callback) = 0;
virtual IEventBlock* createEventBlock(StatusType* status, const char** events) = 0;
virtual IDecFloat16* getDecFloat16(StatusType* status) = 0;
virtual IDecFloat34* getDecFloat34(StatusType* status) = 0;
};
template <typename Name, typename StatusType, typename Base>
@ -16356,6 +16522,192 @@ namespace Firebird
virtual void registerProcedure(StatusType* status, const char* name, IUdrProcedureFactory* factory) = 0;
virtual void registerTrigger(StatusType* status, const char* name, IUdrTriggerFactory* factory) = 0;
};
template <typename Name, typename StatusType, typename Base>
class IDecFloat16BaseImpl : public Base
{
public:
typedef IDecFloat16 Declaration;
IDecFloat16BaseImpl(DoNotInherit = DoNotInherit())
{
static struct VTableImpl : Base::VTable
{
VTableImpl()
{
this->version = Base::VERSION;
this->scatter = &Name::cloopscatterDispatcher;
this->toStr = &Name::clooptoStrDispatcher;
this->gather = &Name::cloopgatherDispatcher;
this->fromStr = &Name::cloopfromStrDispatcher;
}
} vTable;
this->cloopVTable = &vTable;
}
static void CLOOP_CARG cloopscatterDispatcher(IDecFloat16* self, const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp) throw()
{
try
{
static_cast<Name*>(self)->Name::scatter(from, sign, bcd, exp);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG clooptoStrDispatcher(IDecFloat16* self, const FB_DEC16* from, char* to) throw()
{
try
{
static_cast<Name*>(self)->Name::toStr(from, to);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG cloopgatherDispatcher(IDecFloat16* self, int sign, const unsigned char* bcd, int exp, FB_DEC16* to) throw()
{
try
{
static_cast<Name*>(self)->Name::gather(sign, bcd, exp, to);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG cloopfromStrDispatcher(IDecFloat16* self, IStatus* status, const char* from, FB_DEC16* to) throw()
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::fromStr(&status2, from, to);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
};
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IDecFloat16> > >
class IDecFloat16Impl : public IDecFloat16BaseImpl<Name, StatusType, Base>
{
protected:
IDecFloat16Impl(DoNotInherit = DoNotInherit())
{
}
public:
virtual ~IDecFloat16Impl()
{
}
virtual void scatter(const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp) = 0;
virtual void toStr(const FB_DEC16* from, char* to) = 0;
virtual void gather(int sign, const unsigned char* bcd, int exp, FB_DEC16* to) = 0;
virtual void fromStr(StatusType* status, const char* from, FB_DEC16* to) = 0;
};
template <typename Name, typename StatusType, typename Base>
class IDecFloat34BaseImpl : public Base
{
public:
typedef IDecFloat34 Declaration;
IDecFloat34BaseImpl(DoNotInherit = DoNotInherit())
{
static struct VTableImpl : Base::VTable
{
VTableImpl()
{
this->version = Base::VERSION;
this->scatter = &Name::cloopscatterDispatcher;
this->toStr = &Name::clooptoStrDispatcher;
this->gather = &Name::cloopgatherDispatcher;
this->fromStr = &Name::cloopfromStrDispatcher;
}
} vTable;
this->cloopVTable = &vTable;
}
static void CLOOP_CARG cloopscatterDispatcher(IDecFloat34* self, const FB_DEC34* from, int* sign, unsigned char* bcd, int* exp) throw()
{
try
{
static_cast<Name*>(self)->Name::scatter(from, sign, bcd, exp);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG clooptoStrDispatcher(IDecFloat34* self, const FB_DEC34* from, char* to) throw()
{
try
{
static_cast<Name*>(self)->Name::toStr(from, to);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG cloopgatherDispatcher(IDecFloat34* self, int sign, const unsigned char* bcd, int exp, FB_DEC34* to) throw()
{
try
{
static_cast<Name*>(self)->Name::gather(sign, bcd, exp, to);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG cloopfromStrDispatcher(IDecFloat34* self, IStatus* status, const char* from, FB_DEC34* to) throw()
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::fromStr(&status2, from, to);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
};
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IDecFloat34> > >
class IDecFloat34Impl : public IDecFloat34BaseImpl<Name, StatusType, Base>
{
protected:
IDecFloat34Impl(DoNotInherit = DoNotInherit())
{
}
public:
virtual ~IDecFloat34Impl()
{
}
virtual void scatter(const FB_DEC34* from, int* sign, unsigned char* bcd, int* exp) = 0;
virtual void toStr(const FB_DEC34* from, char* to) = 0;
virtual void gather(int sign, const unsigned char* bcd, int exp, FB_DEC34* to) = 0;
virtual void fromStr(StatusType* status, const char* from, FB_DEC34* to) = 0;
};
};

View File

@ -133,6 +133,14 @@
builder->setType(status, index, SQL_DOUBLE); \
builder->setLength(status, index, sizeof(double));
#define FB__META_FB_DECFLOAT16 \
builder->setType(status, index, SQL_DEC16); \
builder->setLength(status, index, sizeof(FB_DEC16));
#define FB__META_FB_DECFLOAT34 \
builder->setType(status, index, SQL_DEC34); \
builder->setLength(status, index, sizeof(FB_DEC34));
#define FB__META_FB_BLOB \
builder->setType(status, index, SQL_BLOB); \
builder->setLength(status, index, sizeof(ISC_QUAD));
@ -185,6 +193,8 @@
#define FB__TYPE_FB_BIGINT ISC_INT64
#define FB__TYPE_FB_FLOAT float
#define FB__TYPE_FB_DOUBLE double
#define FB__TYPE_FB_DECFLOAT16 FB_DEC16
#define FB__TYPE_FB_DECFLOAT34 FB_DEC34
#define FB__TYPE_FB_BLOB ISC_QUAD
#define FB__TYPE_FB_BOOLEAN ISC_UCHAR
#define FB__TYPE_FB_DATE ::Firebird::FbDate

View File

@ -170,4 +170,14 @@ typedef struct GDS_QUAD_t ISC_QUAD;
typedef int (*FB_SHUTDOWN_CALLBACK)(const int reason, const int mask, void* arg);
struct FB_DEC16_t {
ISC_UINT64 fb_data[1];
};
struct FB_DEC34_t {
ISC_UINT64 fb_data[2];
};
typedef struct FB_DEC16_t FB_DEC16;
typedef struct FB_DEC34_t FB_DEC34;
#endif /* INCLUDE_TYPES_PUB_H */

View File

@ -309,6 +309,16 @@ static inline int fb_isdigit(const char c)
}
IsqlGlobals::IsqlGlobals()
{
Firebird::AutoPtr<Firebird::IStatus, Firebird::SimpleDispose<Firebird::IStatus> >
status_vector(fbMaster->getStatus());
Firebird::CheckStatusWrapper statusWrapper(status_vector);
df16 = Firebird::UtilInterfacePtr()->getDecFloat16(&statusWrapper);
df34 = Firebird::UtilInterfacePtr()->getDecFloat34(&statusWrapper);
}
// I s q l G l o b a l s : : p r i n t f
// Output to the Out stream.
void IsqlGlobals::printf(const char* buffer, ...)
@ -2223,8 +2233,8 @@ static processing_state add_row(TEXT* tabname)
SINT64 n;
float* fvalue;
double* dvalue;
Firebird::Decimal64* d64value;
Firebird::Decimal128* d128value;
FB_DEC16* d64value;
FB_DEC34* d128value;
UCHAR* boolean;
ISC_QUAD* blobid;
vary* avary;
@ -2291,26 +2301,22 @@ static processing_state add_row(TEXT* tabname)
}
break;
case SQL_DEC64:
d64value = (Firebird::Decimal64*) datap;
try
{
d64value->set(lastInputLine, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
case SQL_DEC16:
d64value = (FB_DEC16*) datap;
if (isqlGlob.df16)
isqlGlob.df16->fromStr(fbStatus, lastInputLine, d64value);
if ((!isqlGlob.df16) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
{
STDERROUT("Input parsing problem");
done = true;
}
break;
case SQL_DEC128:
d128value = (Firebird::Decimal128*) datap;
try
{
d128value->set(lastInputLine, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
case SQL_DEC34:
d128value = (FB_DEC34*) datap;
if (isqlGlob.df34)
isqlGlob.df34->fromStr(fbStatus, lastInputLine, d128value);
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
{
STDERROUT("Input parsing problem");
done = true;
@ -3006,8 +3012,8 @@ static processing_state bulk_insert_hack(const char* command)
vary* avary;
char* achar;
tm times;
Firebird::Decimal64* d64value;
Firebird::Decimal128* d128value;
FB_DEC16* d64value;
FB_DEC34* d128value;
// Initialize the time structure.
memset(&times, 0, sizeof(times));
char msec_str[5] = "";
@ -3067,26 +3073,22 @@ static processing_state bulk_insert_hack(const char* command)
}
break;
case SQL_DEC64:
d64value = (Firebird::Decimal64*) datap;
try
{
d64value->set(lastPos, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
case SQL_DEC16:
d64value = (FB_DEC16*) datap;
if (isqlGlob.df16)
isqlGlob.df16->fromStr(fbStatus, lastInputLine, d64value);
if ((!isqlGlob.df16) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
{
STDERROUT("Input parsing problem");
done = true;
}
break;
case SQL_DEC128:
d128value = (Firebird::Decimal128*) datap;
try
{
d128value->set(lastPos, isqlGlob.decStatus);
}
catch (const Firebird::Exception&)
case SQL_DEC34:
d128value = (FB_DEC34*) datap;
if (isqlGlob.df34)
isqlGlob.df34->fromStr(fbStatus, lastInputLine, d128value);
if ((!isqlGlob.df34) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
{
STDERROUT("Input parsing problem");
done = true;
@ -7230,10 +7232,13 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
}
break;
case SQL_DEC64:
case SQL_DEC16:
{
char decStr[DECDOUBLE_String];
var->value.asDec64->toString(isqlGlob.decStatus, sizeof(decStr), decStr);
char decStr[Firebird::IDecFloat16::STRING_SIZE];
if (isqlGlob.df16)
isqlGlob.df16->toStr(var->value.asDec16, decStr);
else
strcpy(decStr, "Conversion error");
if (setValues.List)
isqlGlob.printf("%*.*s%s", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr, NEWLINE);
@ -7242,10 +7247,13 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
}
break;
case SQL_DEC128:
case SQL_DEC34:
{
char decStr[DECQUAD_String];
var->value.asDec128->toString(isqlGlob.decStatus, sizeof(decStr), decStr);
char decStr[Firebird::IDecFloat34::STRING_SIZE];
if (isqlGlob.df34)
isqlGlob.df34->toStr(var->value.asDec34, decStr);
else
strcpy(decStr, "Conversion error");
if (setValues.List)
isqlGlob.printf("%*.*s%s", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr, NEWLINE);
@ -8057,10 +8065,10 @@ static unsigned process_message_display(Firebird::IMessageMetadata* message, uns
case SQL_DOUBLE:
disp_length = DOUBLE_LEN;
break;
case SQL_DEC64:
case SQL_DEC16:
disp_length = DECDOUBLE_String - 1;
break;
case SQL_DEC128:
case SQL_DEC34:
disp_length = DECQUAD_String - 1;
break;
case SQL_TEXT:
@ -8715,9 +8723,9 @@ static const char* sqltype_to_string(unsigned sqltype)
return "FLOAT";
case SQL_DOUBLE:
return "DOUBLE";
case SQL_DEC64:
case SQL_DEC16:
return "DECFLOAT(16)";
case SQL_DEC128:
case SQL_DEC34:
return "DECFLOAT(34)";
case SQL_D_FLOAT:
return "D_FLOAT";

View File

@ -35,7 +35,7 @@
#include "../jrd/flags.h"
#include <stdlib.h>
#include "../common/DecFloat.h"
#include <firebird/Interface.h>
// Define lengths used in isql.e
@ -402,13 +402,12 @@ public:
USHORT major_ods;
USHORT minor_ods;
USHORT att_charset;
Firebird::DecimalStatus decStatus;
Firebird::IDecFloat16* df16;
Firebird::IDecFloat34* df34;
void printf(const char* buffer, ...);
void prints(const char* buffer);
IsqlGlobals()
: decStatus(DEC_Errors)
{ }
IsqlGlobals();
};
extern IsqlGlobals isqlGlob;
@ -462,8 +461,8 @@ struct IsqlVar
ISC_QUAD* blobid;
vary* asVary;
char* asChar;
Firebird::Decimal64* asDec64;
Firebird::Decimal128* asDec128;
FB_DEC16* asDec16;
FB_DEC34* asDec34;
void* setPtr;
};
TypeMix value;

View File

@ -100,12 +100,12 @@ namespace
break;
case dtype_dec64:
item.type = SQL_DEC64;
item.type = SQL_DEC16;
item.length = sizeof(Decimal64);
break;
case dtype_dec128:
item.type = SQL_DEC128;
item.type = SQL_DEC34;
item.length = sizeof(Decimal128);
break;

View File

@ -15,6 +15,8 @@
ISC_DATE = Integer;
ISC_TIME = Integer;
ISC_QUAD = array [1..2] of Integer;
FB_DEC16 = array [1..1] of Int64;
FB_DEC34 = array [1..2] of Int64;
ntrace_relation_t = Integer;
TraceCounts = Record

View File

@ -117,12 +117,12 @@ void BlrFromMessage::buildBlr(IMessageMetadata* metadata)
dtype = dtype_text;
break;
case SQL_DEC64:
case SQL_DEC16:
appendUChar(blr_dec64);
dtype = dtype_dec64;
break;
case SQL_DEC128:
case SQL_DEC34:
appendUChar(blr_dec128);
dtype = dtype_dec128;
break;

View File

@ -588,6 +588,8 @@ public:
unsigned setOffsets(Firebird::CheckStatusWrapper* status, Firebird::IMessageMetadata* metadata,
Firebird::IOffsetsCallback* callback);
Firebird::IEventBlock* createEventBlock(Firebird::CheckStatusWrapper* status, const char** events);
Firebird::IDecFloat16* getDecFloat16(Firebird::CheckStatusWrapper* status);
Firebird::IDecFloat34* getDecFloat34(Firebird::CheckStatusWrapper* status);
};
} // namespace Why

View File

@ -1057,6 +1057,86 @@ IXpbBuilder* UtilInterface::getXpbBuilder(CheckStatusWrapper* status,
}
}
class DecFloat16 FB_FINAL : public AutoIface<IDecFloat16Impl<DecFloat16, CheckStatusWrapper> >
{
public:
// IDecFloat16 implementation
void scatter(const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp)
{
*sign = decDoubleToBCD(reinterpret_cast<const decDouble*>(from), exp, bcd);
}
void toStr(const FB_DEC16* from, char* to)
{
decDoubleToString(reinterpret_cast<const decDouble*>(from), to);
}
void gather(int sign, const unsigned char* bcd, int exp, FB_DEC16* to)
{
decDoubleFromBCD(reinterpret_cast<decDouble*>(to), exp, bcd, sign ? DECFLOAT_Sign : 0);
}
void fromStr(CheckStatusWrapper* status, const char* from, FB_DEC16* to)
{
try
{
DecimalStatus decSt(DEC_Errors);
Decimal64* val = reinterpret_cast<Decimal64*>(to);
val->set(from, decSt);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
};
IDecFloat16* UtilInterface::getDecFloat16(CheckStatusWrapper* status)
{
static DecFloat16 decFloat16;
return &decFloat16;
}
class DecFloat34 FB_FINAL : public AutoIface<IDecFloat34Impl<DecFloat34, CheckStatusWrapper> >
{
public:
// IDecFloat34 implementation
void scatter(const FB_DEC34* from, int* sign, unsigned char* bcd, int* exp)
{
*sign = decQuadToBCD(reinterpret_cast<const decQuad*>(from), exp, bcd);
}
void toStr(const FB_DEC34* from, char* to)
{
decQuadToString(reinterpret_cast<const decQuad*>(from), to);
}
void gather(int sign, const unsigned char* bcd, int exp, FB_DEC34* to)
{
decQuadFromBCD(reinterpret_cast<decQuad*>(to), exp, bcd, sign ? DECFLOAT_Sign : 0);
}
void fromStr(CheckStatusWrapper* status, const char* from, FB_DEC34* to)
{
try
{
DecimalStatus decSt(DEC_Errors);
Decimal128* val = reinterpret_cast<Decimal128*>(to);
val->set(from, decSt);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
};
IDecFloat34* UtilInterface::getDecFloat34(CheckStatusWrapper* status)
{
static DecFloat34 decFloat34;
return &decFloat34;
}
unsigned UtilInterface::setOffsets(CheckStatusWrapper* status, IMessageMetadata* metadata,
IOffsetsCallback* callback)
{