#pragma once #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int ILLEGAL_TYPE_OF_ARGUMENT; extern const int ILLEGAL_COLUMN; } /** formatReadableSize - prints the transferred size in bytes in form `123.45 GiB`. * formatReadableQuantity - prints the quantity in form of 123 million. */ template class FunctionFormatReadable : public IFunction { public: static constexpr auto name = Impl::name; static FunctionPtr create(ContextPtr) { return std::make_shared>(); } String getName() const override { return name; } size_t getNumberOfArguments() const override { return 1; } DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override { const IDataType & type = *arguments[0]; if (!isNativeNumber(type)) throw Exception("Cannot format " + type.getName() + " because it's not a native numeric type", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); return std::make_shared(); } bool useDefaultImplementationForConstants() const override { return true; } ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override { ColumnPtr res; if (!((res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)) || (res = executeType(arguments)))) throw Exception("Illegal column " + arguments[0].column->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN); return res; } private: template ColumnPtr executeType(const ColumnsWithTypeAndName & arguments) const { if (const ColumnVector * col_from = checkAndGetColumn>(arguments[0].column.get())) { auto col_to = ColumnString::create(); const typename ColumnVector::Container & vec_from = col_from->getData(); ColumnString::Chars & data_to = col_to->getChars(); ColumnString::Offsets & offsets_to = col_to->getOffsets(); size_t size = vec_from.size(); data_to.resize(size * 2); offsets_to.resize(size); WriteBufferFromVector buf_to(data_to); for (size_t i = 0; i < size; ++i) { Impl::format(static_cast(vec_from[i]), buf_to); writeChar(0, buf_to); offsets_to[i] = buf_to.count(); } buf_to.finalize(); return col_to; } return nullptr; } }; }