DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
    {
        const IDataType & type = *arguments[0];
        if (type.isValueUnambiguouslyRepresentedInContiguousMemoryRegion())
            return std::make_shared<DataTypeString>();
        throw Exception("Cannot reinterpret " + type.getName() + " as String because it is not contiguous in memory", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
    }
    static void executeToString(const IColumn & src, ColumnString & dst)
    {
        size_t rows = src.size();
        ColumnString::Chars & data_to = dst.getChars();
        ColumnString::Offsets & offsets_to = dst.getOffsets();
        offsets_to.resize(rows);
        ColumnString::Offset offset = 0;
        for (size_t i = 0; i < rows; ++i)
        {
            StringRef data = src.getDataAt(i);
            
            while (data.size && data.data[data.size - 1] == 0)
                --data.size;
            data_to.resize(offset + data.size + 1);
            memcpySmallAllowReadWriteOverflow15(&data_to[offset], data.data, data.size);
            offset += data.size;
            data_to[offset] = 0;
            ++offset;
            offsets_to[i] = offset;
        }
    }
    bool useDefaultImplementationForConstants() const override { return true; }