Formatting; fixed error; fixed memory leak; miscellaneous #2770

This commit is contained in:
Alexey Milovidov 2018-09-18 19:42:25 +03:00
parent dde8ca03cf
commit ac73431451

View File

@ -1580,16 +1580,14 @@ private:
{ {
public: public:
FormattingOperation(const char * source, size_t copy_source, size_t copy_length) FormattingOperation(const char * source, size_t copy_source, size_t copy_length)
: source(source), source_position_to_copy(copy_source), source_length_to_copy(copy_length) { : source(source), source_position_to_copy(copy_source), source_length_to_copy(copy_length) {}
operation = nullptr;
}
FormattingOperation(const char * source) : source(source) {} FormattingOperation(const char * source) : source(source) {}
void (*operation)(char *&, UInt32, const DateLUTImpl &); void (*operation)(char *&, UInt32, const DateLUTImpl &) = nullptr;
private:
static constexpr char kDigits[] = "0123456789"; private:
static constexpr char digits[] = "0123456789";
const char * source; const char * source;
size_t source_position_to_copy = 0; size_t source_position_to_copy = 0;
size_t source_length_to_copy = 0; size_t source_length_to_copy = 0;
@ -1606,22 +1604,23 @@ private:
auto width_copy = width; auto width_copy = width;
ep += width_copy; ep += width_copy;
do { do
{
--width; --width;
*--ep = kDigits[v % 10]; *--ep = digits[v % 10]; /// TODO v % 10 + '0' should be better (one arithmetic op vs. load from L1 cache)
} while (v /= 10); } while (v /= 10);
while (--width >= 0) *--ep = '0'; while (--width >= 0)
*--ep = '0';
ep += width_copy; ep += width_copy;
} }
public: public:
// format DateTime // format DateTime
void action(char *& target, UInt32 source, const DateLUTImpl & timezone) void action(char *& target, UInt32 source, const DateLUTImpl & timezone)
{ {
if(operation) if (operation)
operation(target, source, timezone); operation(target, source, timezone);
else else
copy(target, source, timezone); copy(target, source, timezone);
@ -1630,22 +1629,22 @@ private:
// format Date (convert to DateTime implicitly) // format Date (convert to DateTime implicitly)
void action(char *& target, UInt16 date, const DateLUTImpl & timezone) void action(char *& target, UInt16 date, const DateLUTImpl & timezone)
{ {
/// TODO This is not efficient.
const UInt32 datetime = timezone.fromDayNum(DayNum(date)); const UInt32 datetime = timezone.fromDayNum(DayNum(date));
action(target, datetime, timezone); action(target, datetime, timezone);
} }
void copy(char *& target, UInt32 , const DateLUTImpl & ) void copy(char *& target, UInt32, const DateLUTImpl &)
{ {
auto tmp = source + source_position_to_copy; memcpy(target, source + source_position_to_copy, source_length_to_copy);
memcpy(target, tmp, source_length_to_copy); target += source_length_to_copy;
target += source_length_to_copy * sizeof(char);
} }
static void format_C(char *& target, UInt32 source, const DateLUTImpl & timezone) static void format_C(char *& target, UInt32 source, const DateLUTImpl & timezone)
{ {
auto year = ToYearImpl::execute(source, timezone); auto year = ToYearImpl::execute(source, timezone);
int s = static_cast<int>(floor(year/100)); auto century = year / 100;
writeNumber2(target, s); writeNumber2(target, century);
} }
static void format_d(char *& target, UInt32 source, const DateLUTImpl & timezone) static void format_d(char *& target, UInt32 source, const DateLUTImpl & timezone)
@ -1657,7 +1656,7 @@ private:
{ {
auto month = ToMonthImpl::execute(source, timezone); auto month = ToMonthImpl::execute(source, timezone);
auto day = ToDayOfMonthImpl::execute(source, timezone); auto day = ToDayOfMonthImpl::execute(source, timezone);
auto year = ToYearImpl::execute(source, timezone) % 1000; auto year = ToYearImpl::execute(source, timezone) % 100;
writeNumber2(target, month); writeNumber2(target, month);
*target++ = '/'; *target++ = '/';
writeNumber2(target, day); writeNumber2(target, day);
@ -1669,7 +1668,8 @@ private:
{ {
auto day = ToDayOfMonthImpl::execute(source, timezone); auto day = ToDayOfMonthImpl::execute(source, timezone);
if (day < 10) { if (day < 10)
{
*target++ = ' '; *target++ = ' ';
*target++ = '0' + day; *target++ = '0' + day;
} }
@ -1698,8 +1698,7 @@ private:
static void format_I(char *& target, UInt32 source, const DateLUTImpl & timezone) static void format_I(char *& target, UInt32 source, const DateLUTImpl & timezone)
{ {
auto x = ToHourImpl::execute(source, timezone); auto x = ToHourImpl::execute(source, timezone);
auto mod = x % 12; writeNumber2(target, x > 12 ? x - 12 : x);
writeNumber2(target, mod == 0 ? 12 : mod);
} }
static void format_j(char *& target, UInt32 source, const DateLUTImpl & timezone) static void format_j(char *& target, UInt32 source, const DateLUTImpl & timezone)
@ -1726,11 +1725,7 @@ private:
static void format_p(char *& target, UInt32 source, const DateLUTImpl & timezone) static void format_p(char *& target, UInt32 source, const DateLUTImpl & timezone)
{ {
if (ToHourImpl::execute(source, timezone) < 12) *target++ = ToHourImpl::execute(source, timezone) < 12 ? 'A' : 'P';
*target++ = 'A';
else
*target++ = 'P';
*target++ = 'M'; *target++ = 'M';
} }
@ -1817,7 +1812,7 @@ private:
public: public:
static constexpr auto name = "formatDateTime"; static constexpr auto name = "formatDateTime";
static FunctionPtr create(const Context &) { return std::make_shared<FunctionFormatDateTime>(); }; static FunctionPtr create(const Context &) { return std::make_shared<FunctionFormatDateTime>(); }
String getName() const override String getName() const override
{ {
@ -1903,16 +1898,15 @@ public:
for (size_t i = 0; i < vec.size(); ++i) for (size_t i = 0; i < vec.size(); ++i)
{ {
for(auto & instruction : instructions) { for(auto & instruction : instructions)
instruction.action(pos, vec[i], time_zone); instruction.action(pos, vec[i], time_zone);
}
*pos++ = '\0'; *pos++ = '\0';
dst_offsets[i] = pos - begin; dst_offsets[i] = pos - begin;
} }
dst_data.resize(pos - begin); dst_data.resize(pos - begin);
block.getByPosition(result).column = std::move(col_res); block.getByPosition(result).column = std::move(col_res);
return true; return true;
} }
@ -1924,24 +1918,26 @@ public:
char * begin_of_pattern = pattern.data(); char * begin_of_pattern = pattern.data();
size_t result_size = 0; size_t result_size = 0;
size_t last_pos = 0; size_t last_pos = 0;
for (size_t s = 0; s < pattern.length(); s++) {
if(pattern[s] == '%') for (size_t s = 0; s < pattern.length(); ++s)
{
if (pattern[s] == '%')
{ {
if (last_pos > 0) if (last_pos > 0)
{ {
auto length = 1 + s - last_pos; auto length = 1 + s - last_pos;
instructions.push_back(FormattingOperation(begin_of_pattern, last_pos - 1, length)); instructions.emplace_back(begin_of_pattern, last_pos - 1, length);
last_pos = 0; last_pos = 0;
result_size += length; result_size += length;
} }
auto formatting_operation = new FormattingOperation(begin_of_pattern, 0,0); FormattingOperation formatting_operation(begin_of_pattern, 0, 0);
void (*operation)(char *&, UInt32, const DateLUTImpl &) = nullptr; auto & operation = formatting_operation.operation;
if (++s == pattern.length()) if (++s == pattern.length())
throw Exception("Sign '%' is last in pattern, if you need it, use '%%'", ErrorCodes::BAD_ARGUMENTS); throw Exception("Sign '%' is last in pattern, if you need it, use '%%'", ErrorCodes::BAD_ARGUMENTS);
switch(pattern[s]) switch (pattern[s])
{ {
// Year, divided by 100, zero-padded // Year, divided by 100, zero-padded
case 'C': case 'C':
@ -2090,27 +2086,25 @@ public:
default: default:
throw Exception( throw Exception(
"Wrong pattern '" + pattern + "', unexpected symbol '" + pattern[s] + "' for function " + getName(), ErrorCodes::ILLEGAL_COLUMN); "Wrong pattern '" + pattern + "', unexpected symbol '" + pattern[s] + "' for function " + getName(), ErrorCodes::ILLEGAL_COLUMN);
} }
if(operation) instructions.emplace_back(std::move(formatting_operation));
formatting_operation->operation = operation;
instructions.push_back(*formatting_operation);
} }
else { else
if (last_pos == 0) { {
if (last_pos == 0)
last_pos = s + 1; last_pos = s + 1;
}
} }
} }
if (last_pos > 0) if (last_pos > 0)
{ {
auto length = 1 + pattern.length() - last_pos; auto length = 1 + pattern.length() - last_pos;
instructions.push_back(FormattingOperation(begin_of_pattern, last_pos - 1, length)); instructions.emplace_back(begin_of_pattern, last_pos - 1, length);
result_size += length; result_size += length;
} }
return result_size; return result_size;
} }
}; };