From 324c3bb81e0a5737c887cc2fecb2d077162cbc97 Mon Sep 17 00:00:00 2001 From: Yakov Olkhovskiy Date: Tue, 15 Nov 2022 04:57:08 +0000 Subject: [PATCH] fix bin, hex --- .../FunctionsBinaryRepresentation.cpp | 86 ++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/src/Functions/FunctionsBinaryRepresentation.cpp b/src/Functions/FunctionsBinaryRepresentation.cpp index 5f256f60e46..9263ba1c0b8 100644 --- a/src/Functions/FunctionsBinaryRepresentation.cpp +++ b/src/Functions/FunctionsBinaryRepresentation.cpp @@ -326,7 +326,9 @@ public: tryExecuteDecimal(column, res_column) || tryExecuteDecimal(column, res_column) || tryExecuteDecimal(column, res_column) || - tryExecuteUUID(column, res_column)) + tryExecuteUUID(column, res_column) || + tryExecuteIPv4(column, res_column) || + tryExecuteIPv6(column, res_column)) return res_column; throw Exception("Illegal column " + arguments[0].column->getName() @@ -548,6 +550,88 @@ public: return false; } } + + bool tryExecuteIPv6(const IColumn * col, ColumnPtr & col_res) const + { + const ColumnIPv6 * col_vec = checkAndGetColumn(col); + + static constexpr size_t MAX_LENGTH = sizeof(IPv6) * word_size + 1; /// Including trailing zero byte. + + if (!col_vec) + return false; + + auto col_str = ColumnString::create(); + ColumnString::Chars & out_vec = col_str->getChars(); + ColumnString::Offsets & out_offsets = col_str->getOffsets(); + + const typename ColumnIPv6::Container & in_vec = col_vec->getData(); + const IPv6* ip = in_vec.data(); + + size_t size = in_vec.size(); + out_offsets.resize(size); + out_vec.resize(size * (word_size+1) + MAX_LENGTH); /// word_size+1 is length of one byte in hex/bin plus zero byte. + + size_t pos = 0; + for (size_t i = 0; i < size; ++i) + { + /// Manual exponential growth, so as not to rely on the linear amortized work time of `resize` (no one guarantees it). + if (pos + MAX_LENGTH > out_vec.size()) + out_vec.resize(out_vec.size() * word_size + MAX_LENGTH); + + char * begin = reinterpret_cast(&out_vec[pos]); + char * end = begin; + + Impl::executeOneString(reinterpret_cast(&ip[i].toUnderType().items[0]), reinterpret_cast(&ip[i].toUnderType().items[2]), end); + + pos += end - begin; + out_offsets[i] = pos; + } + out_vec.resize(pos); + + col_res = std::move(col_str); + return true; + } + + bool tryExecuteIPv4(const IColumn * col, ColumnPtr & col_res) const + { + const ColumnIPv4 * col_vec = checkAndGetColumn(col); + + static constexpr size_t MAX_LENGTH = sizeof(IPv4) * word_size + 1; /// Including trailing zero byte. + + if (!col_vec) + return false; + + auto col_str = ColumnString::create(); + ColumnString::Chars & out_vec = col_str->getChars(); + ColumnString::Offsets & out_offsets = col_str->getOffsets(); + + const typename ColumnIPv4::Container & in_vec = col_vec->getData(); + const IPv4* ip = in_vec.data(); + + size_t size = in_vec.size(); + out_offsets.resize(size); + out_vec.resize(size * (word_size+1) + MAX_LENGTH); /// word_size+1 is length of one byte in hex/bin plus zero byte. + + size_t pos = 0; + for (size_t i = 0; i < size; ++i) + { + /// Manual exponential growth, so as not to rely on the linear amortized work time of `resize` (no one guarantees it). + if (pos + MAX_LENGTH > out_vec.size()) + out_vec.resize(out_vec.size() * word_size + MAX_LENGTH); + + char * begin = reinterpret_cast(&out_vec[pos]); + char * end = begin; + + Impl::executeOneUIntOrInt(ip[i].toUnderType(), end); + + pos += end - begin; + out_offsets[i] = pos; + } + out_vec.resize(pos); + + col_res = std::move(col_str); + return true; + } }; /// Decode number or string from string with binary or hexadecimal representation