1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

Fix regression in a query involving an aggregate function on a

non-wide decimal column in the HAVING clause.

In buildAggregateColumn(), if an aggregate function (such as avg)
is applied on a non-wide decimal column, we were setting the precision
of the resulting column as -1. This later down in the execution got
converted to 255 as in some cases, precision is stored as uint8_t.
The predicate operations on a DECIMAL column has logic that uses
the wide Decimal::s128value field if precision > 18. This logic incorrectly
used the Decimal::s128value instead of the correct value stored in the
narrow Decimal::value field, since precision of the Decimal column
was 255. The fix is to set the aggregate column precision to
datatypes::INT64MAXPRECISION (18) in buildAggregateColumn() when the
aggregate is applied on a non-wide decimal column.

This commit also partially fixes -Wstrict-aliasing GCC warnings.
This commit is contained in:
Gagan Goel
2021-06-22 06:53:47 +00:00
parent c6f4f00b0d
commit 7c8b502dc2
4 changed files with 40 additions and 18 deletions

View File

@ -85,8 +85,6 @@ constexpr uint8_t INT64MAXPRECISION = 18U;
constexpr uint8_t INT128MAXPRECISION = 38U; constexpr uint8_t INT128MAXPRECISION = 38U;
constexpr uint8_t MAXLEGACYWIDTH = 8U; constexpr uint8_t MAXLEGACYWIDTH = 8U;
constexpr uint8_t MAXSCALEINC4AVG = 4U; constexpr uint8_t MAXSCALEINC4AVG = 4U;
constexpr int8_t IGNOREPRECISION = -1;
const uint64_t mcs_pow_10[20] = const uint64_t mcs_pow_10[20] =

View File

@ -5068,7 +5068,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
{ {
ct.scale += datatypes::MAXSCALEINC4AVG; ct.scale += datatypes::MAXSCALEINC4AVG;
} }
ct.precision = datatypes::IGNOREPRECISION; ct.precision = datatypes::INT64MAXPRECISION;
} }
ac->resultType(ct); ac->resultType(ct);
} }

View File

@ -353,7 +353,7 @@ class Hash128
public: public:
inline size_t operator()(const int128_t i) const inline size_t operator()(const int128_t i) const
{ {
return *reinterpret_cast<const uint64_t*>(&i); return (uint64_t)((int64_t) i);
} }
}; };

View File

@ -105,6 +105,27 @@ bool number_value ( const string& data )
namespace dataconvert namespace dataconvert
{ {
// LE stands for Little Endian
uint32_t getUInt32LE(const char* ptr)
{
return reinterpret_cast<const uint32_t*>(ptr)[0];
}
int32_t getSInt32LE(const char* ptr)
{
return reinterpret_cast<const int32_t*>(ptr)[0];
}
uint64_t getUInt64LE(const char* ptr)
{
return reinterpret_cast<const uint64_t*>(ptr)[0];
}
int64_t getSInt64LE(const char* ptr)
{
return reinterpret_cast<const int64_t*>(ptr)[0];
}
template <typename T> template <typename T>
void number_int_value(const string& data, void number_int_value(const string& data,
cscDataType typeCode, cscDataType typeCode,
@ -1627,7 +1648,7 @@ DataConvert::StringToDate(const std::string& data, bool& pushWarning)
if (stringToDateStruct(data, aDay)) if (stringToDateStruct(data, aDay))
{ {
boost::any value = (*(reinterpret_cast<uint32_t*> (&aDay))); boost::any value = getUInt32LE((const char*) &aDay);
return value; return value;
} }
boost::any value = (uint32_t) 0; boost::any value = (uint32_t) 0;
@ -1643,7 +1664,7 @@ DataConvert::StringToDatetime(const std::string& data, bool& pushWarning)
if (stringToDatetimeStruct(data, aDatetime, 0)) // QQ: why 0? if (stringToDatetimeStruct(data, aDatetime, 0)) // QQ: why 0?
{ {
boost::any value = *(reinterpret_cast<uint64_t*>(&aDatetime)); boost::any value = getUInt64LE((const char*) &aDatetime);
return value; return value;
} }
boost::any value = (uint64_t) 0; boost::any value = (uint64_t) 0;
@ -1664,7 +1685,7 @@ DataConvert::StringToTime(const datatypes::SystemCatalog::TypeAttributesStd& col
pushWarning = true; pushWarning = true;
} }
boost::any value = (int64_t) * (reinterpret_cast<int64_t*>(&aTime)); boost::any value = getSInt64LE((const char*) &aTime);
return value; return value;
} }
@ -1681,7 +1702,7 @@ DataConvert::StringToTimestamp(const datatypes::ConvertFromStringParam &prm,
pushWarning = true; pushWarning = true;
} }
boost::any value = (uint64_t) *(reinterpret_cast<uint64_t*>(&aTimestamp)); boost::any value = getUInt64LE((const char*) &aTimestamp);
return value; return value;
} }
@ -2448,7 +2469,10 @@ int64_t DataConvert::stringToDate(const string& data)
Date aDay; Date aDay;
if ( stringToDateStruct( data, aDay ) ) if ( stringToDateStruct( data, aDay ) )
return (((*(reinterpret_cast<uint32_t*> (&aDay))) & 0xFFFFFFC0) | 0x3E); {
uint32_t temp = getUInt32LE((const char*) &aDay);
return ((temp & 0xFFFFFFC0) | 0x3E);
}
else else
return -1; return -1;
} }
@ -2458,7 +2482,7 @@ int64_t DataConvert::stringToDatetime(const string& data, bool* date)
DateTime dtime; DateTime dtime;
if ( stringToDatetimeStruct( data, dtime, date ) ) if ( stringToDatetimeStruct( data, dtime, date ) )
return *(reinterpret_cast<uint64_t*>(&dtime)); return getUInt64LE((const char*) &dtime);
else else
return -1; return -1;
} }
@ -2468,7 +2492,7 @@ int64_t DataConvert::stringToTimestamp(const string& data, const string& timeZon
TimeStamp aTimestamp; TimeStamp aTimestamp;
if ( stringToTimestampStruct( data, aTimestamp, timeZone ) ) if ( stringToTimestampStruct( data, aTimestamp, timeZone ) )
return *(reinterpret_cast<uint64_t*>(&aTimestamp)); return getUInt64LE((const char*) &aTimestamp);
else else
return -1; return -1;
} }
@ -2485,7 +2509,7 @@ int64_t DataConvert::intToDate(int64_t data)
aday.year = 0; aday.year = 0;
aday.month = 0; aday.month = 0;
aday.day = 0; aday.day = 0;
return *(reinterpret_cast<uint32_t*>(&aday)); return getUInt32LE((const char*) &aday);
} }
// this snprintf call causes a compiler warning b/c we're potentially copying a 20-digit # // this snprintf call causes a compiler warning b/c we're potentially copying a 20-digit #
@ -2597,7 +2621,7 @@ int64_t DataConvert::intToDate(int64_t data)
aday.year = y; aday.year = y;
aday.month = m; aday.month = m;
aday.day = d; aday.day = d;
return *(reinterpret_cast<uint32_t*>(&aday)); return getUInt32LE((const char*) &aday);
} }
/* This is really painful and expensive b/c it seems the input is not normalized or /* This is really painful and expensive b/c it seems the input is not normalized or
@ -2621,7 +2645,7 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
if (date) if (date)
*date = true; *date = true;
return *(reinterpret_cast<uint64_t*>(&adaytime)); return getUInt64LE((const char*) &adaytime);
} }
// this snprintf call causes a compiler warning b/c we're potentially copying a 20-digit # // this snprintf call causes a compiler warning b/c we're potentially copying a 20-digit #
@ -2747,7 +2771,7 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
if (date) if (date)
*date = isDate; *date = isDate;
return *(reinterpret_cast<uint64_t*>(&adaytime)); return getUInt64LE((const char*) &adaytime);
} }
/* This is really painful and expensive b/c it seems the input is not normalized or /* This is really painful and expensive b/c it seems the input is not normalized or
@ -2767,7 +2791,7 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString)
atime.msecond = 0; atime.msecond = 0;
atime.is_neg = 0; atime.is_neg = 0;
return *(reinterpret_cast<int64_t*>(&atime)); return getSInt64LE((const char*) &atime);
} }
// this snprintf call causes a compiler warning b/c we're potentially copying a 20-digit # // this snprintf call causes a compiler warning b/c we're potentially copying a 20-digit #
@ -2871,7 +2895,7 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString)
atime.msecond = ms; atime.msecond = ms;
atime.is_neg = isNeg; atime.is_neg = isNeg;
return *(reinterpret_cast<int64_t*>(&atime)); return getSInt64LE((const char*) &atime);
} }
int64_t DataConvert::stringToTime(const string& data) int64_t DataConvert::stringToTime(const string& data)
@ -2991,7 +3015,7 @@ int64_t DataConvert::stringToTime(const string& data)
atime.second = sec; atime.second = sec;
atime.msecond = msec; atime.msecond = msec;
atime.is_neg = isNeg; atime.is_neg = isNeg;
return *(reinterpret_cast<int64_t*>(&atime)); return getSInt64LE((const char*) &atime);
} }