connectivity::ORowSetValue cleanup and behaviour
Lionel Elie Mamane
lionel at mamane.lu
Wed Feb 15 04:55:34 PST 2012
Hi,
The connectivity contains a ORowSetValue class, to hold a database
value, along with its type. "Obviously" this class is used all over
the place in our database-related code.
I'm itching to change it in non-trivial ways, and I've hit some
"WTFs", so I thought I'd check if someone knows a good reason for some
of baroque choices made (which would mean my naive "clean" way might
introduce other bugs).
1) Variable-length strings and fixed-length strings never compare
equal. That's what started all this, because of a user-visible bug
consequence.
Errr... They obviously should?
2) Signed integers and unsigned integers never compare equal. But an
unsigned integer compares equal to the corresponding float...
Errr... They obviously should?
3) Unsigned integers are stored weirdly, that is as the next-bigger
size signed integer. Does anybody have *any* clue as to why this
could possibly be a good idea?
Oh, and unsigned 64 bit integer? Just stored as a *string*,
because, you know, we don't have a bigger signed integer at hand.
The data part of the class looks like:
class OOO_DLLPUBLIC_DBTOOLS ORowSetValue
{
union
{
sal_Bool m_bBool;
sal_Int8 m_nInt8;
sal_Int16 m_nInt16;
sal_Int32 m_nInt32;
rtl_uString* m_pString;
void* m_pValue; // can contains double, etc
} m_aValue;
sal_Int32 m_eTypeKind; // the database type
sal_Bool m_bNull : 1; // value is null
sal_Bool m_bBound : 1; // is bound
sal_Bool m_bModified : 1; // value was changed
sal_Bool m_bSigned : 1; // value is signed
}
m_eTypeKind is a tag that says what type the value is: fixed-length
string, variable-length string, 8/16/32/64 bit (un)signed integer,
date, time, timestamp, decimal number, boolean, .... See
offapi/com/sun/star/sdbc/DataType.hdl
My first impulse was to reinterpret_cast<>() unsigned integers into
the *same* size signed integer and back, but actually cleaner to do:
class OOO_DLLPUBLIC_DBTOOLS ORowSetValue
{
union
{
sal_Bool m_bBool;
sal_Int8 m_nInt8;
sal_Int16 m_nInt16;
sal_Int32 m_nInt32;
sal_uInt8 m_nuInt8;
sal_uInt16 m_nuInt16;
sal_uInt32 m_nuInt32;
rtl_uString* m_pString;
void* m_pValue; // can contains double, etc
} m_aValue;
sal_Int32 m_eTypeKind; // the database type
sal_Bool m_bNull : 1; // value is null
sal_Bool m_bBound : 1; // is bound
sal_Bool m_bModified : 1; // value was changed
sal_Bool m_bSigned : 1; // value is signed
}
That much shouldn't change the storage size of that class.
I'm tempted to actually go further and just make the class bigger, so
that we don't have to dynamically allocate storage for double, 64 bit
ints, etc, which (to me at least) seems like a bigger overhead than the
increase in memory:
class OOO_DLLPUBLIC_DBTOOLS ORowSetValue
{
union
{
sal_Bool m_bBool;
sal_Int8 m_nInt8;
sal_Int16 m_nInt16;
sal_Int32 m_nInt32;
sal_Int64 m_nInt64;
sal_uInt8 m_nuInt8;
sal_uInt16 m_nuInt16;
sal_uInt32 m_nuInt32;
sal_uInt64 m_nuInt64;
rtl_uString* m_pString;
float m_fFloat;
double m_fDouble;
void* m_pValue; // for complex types
} m_aValue;
sal_Int32 m_eTypeKind; // the database type
sal_Bool m_bNull : 1; // value is null
sal_Bool m_bBound : 1; // is bound
sal_Bool m_bModified : 1; // value was changed
sal_Bool m_bSigned : 1; // value is signed
}
And since e.g. ::com::sun::star::util::Date and Time are structs of
three or four 16-bit integers, let's stick them in the union, too.
Any opinions, vetos, insights? Am I misguided about the "minimal
memory amount taken vs dynamic allocation overhead" balance?
--
Lionel
More information about the LibreOffice
mailing list