in src/main/cpp/odbcappender.cpp [501:564]
void ODBCAppender::ODBCAppenderPriv::setParameterValues(const spi::LoggingEventPtr& event, Pool& p)
{
for (auto& item : this->parameterValue)
{
if (!item.paramValue || item.paramValueSize <= 0)
;
else if (SQL_C_WCHAR == item.paramType)
{
LogString sbuf;
item.converter->format(event, sbuf, p);
#if LOG4CXX_LOGCHAR_IS_WCHAR_T
std::wstring& tmp = sbuf;
#else
std::wstring tmp;
Transcoder::encode(sbuf, tmp);
#endif
auto dst = (wchar_t*)item.paramValue;
auto charCount = std::min(size_t(item.paramMaxCharCount), tmp.size());
auto copySize = std::min(size_t(item.paramValueSize - 1), charCount * sizeof(wchar_t));
std::memcpy(dst, tmp.data(), copySize);
dst[copySize / sizeof(wchar_t)] = 0;
}
else if (SQL_C_CHAR == item.paramType)
{
LogString sbuf;
item.converter->format(event, sbuf, p);
#if LOG4CXX_LOGCHAR_IS_UTF8
std::string& tmp = sbuf;
#else
std::string tmp;
Transcoder::encode(sbuf, tmp);
#endif
auto dst = (char*)item.paramValue;
auto sz = std::min(size_t(item.paramMaxCharCount), tmp.size());
auto copySize = std::min(size_t(item.paramValueSize - 1), sz * sizeof(char));
std::memcpy(dst, tmp.data(), copySize);
dst[copySize] = 0;
}
else if (SQL_C_TYPE_TIMESTAMP == item.paramType)
{
apr_time_exp_t exploded;
apr_status_t stat = this->timeZone->explode(&exploded, event->getTimeStamp());
if (stat == APR_SUCCESS)
{
auto dst = (SQL_TIMESTAMP_STRUCT*)item.paramValue;
dst->year = 1900 + exploded.tm_year;
dst->month = 1 + exploded.tm_mon;
dst->day = exploded.tm_mday;
dst->hour = exploded.tm_hour;
dst->minute = exploded.tm_min;
dst->second = exploded.tm_sec;
// Prevent '[ODBC SQL Server Driver]Datetime field overflow' by rounding to the target field precision
int roundingExponent = 6 - (int)item.paramMaxCharCount;
if (0 < roundingExponent)
{
int roundingDivisor = (int)std::pow(10, roundingExponent);
dst->fraction = 1000 * roundingDivisor * ((exploded.tm_usec + roundingDivisor / 2) / roundingDivisor);
}
else
dst->fraction = 1000 * exploded.tm_usec;
}
}
}
}