mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +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:
parent
f995ed4408
commit
1b8b7d37f5
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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(×, 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";
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user