void ODBCAppender::ODBCAppenderPriv::setParameterValues()

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;
			}
		}
	}
}