Skip to content

Commit

Permalink
Merge pull request #55095 from Avogar/print-pretty-type-names
Browse files Browse the repository at this point in the history
Add setting to print pretty deep nested types like Tuple/Array/Map
  • Loading branch information
Avogar committed Sep 28, 2023
2 parents 785df77 + 3e28544 commit e8d8c6d
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 10 deletions.
33 changes: 33 additions & 0 deletions docs/en/operations/settings/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -4678,3 +4678,36 @@ The default value is `false`.
``` xml
<validate_tcp_client_information>true</validate_tcp_client_information>
```

## print_pretty_type_names {#print_pretty_type_names}

Allows to print deep-nested type names in a pretty way with indents in `DESCRIBE` query and in `toTypeName()` function.

Example:

```sql
CREATE TABLE test (a Tuple(b String, c Tuple(d Nullable(UInt64), e Array(UInt32), f Array(Tuple(g String, h Map(String, Array(Tuple(i String, j UInt64))))), k Date), l Nullable(String))) ENGINE=Memory;
DESCRIBE TABLE test FORMAT TSVRaw SETTINGS print_pretty_type_names=1;
```

```
a Tuple(
b String,
c Tuple(
d Nullable(UInt64),
e Array(UInt32),
f Array(Tuple(
g String,
h Map(
String,
Array(Tuple(
i String,
j UInt64
))
)
)),
k Date
),
l Nullable(String)
)
```
1 change: 1 addition & 0 deletions src/Core/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,7 @@ class IColumn;
M(Timezone, session_timezone, "", "This setting can be removed in the future due to potential caveats. It is experimental and is not suitable for production usage. The default timezone for current session or query. The server default timezone if empty.", 0) \
M(Bool, allow_create_index_without_type, false, "Allow CREATE INDEX query without TYPE. Query will be ignored. Made for SQL compatibility tests.", 0) \
M(Bool, create_index_ignore_unique, false, "Ignore UNIQUE keyword in CREATE UNIQUE INDEX. Made for SQL compatibility tests.", 0) \
M(Bool, print_pretty_type_names, false, "Print pretty type names in DESCRIBE query and toTypeName() function", 0) \

// End of COMMON_SETTINGS
// Please add settings related to formats into the FORMAT_FACTORY_SETTINGS, move obsolete settings to OBSOLETE_SETTINGS and obsolete format settings to OBSOLETE_FORMAT_SETTINGS.
Expand Down
10 changes: 10 additions & 0 deletions src/DataTypes/DataTypeArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include <Core/NamesAndTypes.h>
#include <Columns/ColumnConst.h>

#include <IO/WriteHelpers.h>
#include <IO/Operators.h>


namespace DB
{
Expand Down Expand Up @@ -59,6 +62,13 @@ size_t DataTypeArray::getNumberOfDimensions() const
return 1 + nested_array->getNumberOfDimensions(); /// Every modern C++ compiler optimizes tail recursion.
}

String DataTypeArray::doGetPrettyName(size_t indent) const
{
WriteBufferFromOwnString s;
s << "Array(" << nested->getPrettyName(indent) << ')';
return s.str();
}


static DataTypePtr create(const ASTPtr & arguments)
{
Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class DataTypeArray final : public IDataType
return "Array(" + nested->getName() + ")";
}

std::string doGetPrettyName(size_t indent) const override;

const char * getFamilyName() const override
{
return "Array";
Expand Down
10 changes: 10 additions & 0 deletions src/DataTypes/DataTypeMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ std::string DataTypeMap::doGetName() const
return s.str();
}

std::string DataTypeMap::doGetPrettyName(size_t indent) const
{
WriteBufferFromOwnString s;
s << "Map(\n"
<< fourSpaceIndent(indent + 1) << key_type->getPrettyName(indent + 1) << ",\n"
<< fourSpaceIndent(indent + 1) << value_type->getPrettyName(indent + 1) << '\n'
<< fourSpaceIndent(indent) << ')';
return s.str();
}

MutableColumnPtr DataTypeMap::createColumn() const
{
return ColumnMap::create(nested->createColumn());
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class DataTypeMap final : public IDataType

TypeIndex getTypeId() const override { return TypeIndex::Map; }
std::string doGetName() const override;
std::string doGetPrettyName(size_t indent) const override;
const char * getFamilyName() const override { return "Map"; }
String getSQLCompatibleName() const override { return "JSON"; }

Expand Down
22 changes: 22 additions & 0 deletions src/DataTypes/DataTypeTuple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,28 @@ std::string DataTypeTuple::doGetName() const
return s.str();
}

std::string DataTypeTuple::doGetPrettyName(size_t indent) const
{
size_t size = elems.size();
WriteBufferFromOwnString s;
s << "Tuple(\n";

for (size_t i = 0; i != size; ++i)
{
if (i != 0)
s << ",\n";

s << fourSpaceIndent(indent + 1);
if (have_explicit_names)
s << backQuoteIfNeed(names[i]) << ' ';

s << elems[i]->getPrettyName(indent + 1);
}

s << '\n' << fourSpaceIndent(indent) << ')';
return s.str();
}


static inline IColumn & extractElementColumn(IColumn & column, size_t idx)
{
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeTuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class DataTypeTuple final : public IDataType

TypeIndex getTypeId() const override { return TypeIndex::Tuple; }
std::string doGetName() const override;
std::string doGetPrettyName(size_t indent) const override;
const char * getFamilyName() const override { return "Tuple"; }
String getSQLCompatibleName() const override { return "JSON"; }

Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/IDataType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <Common/Exception.h>
#include <Common/SipHash.h>
#include <Common/quoteString.h>

#include <IO/WriteHelpers.h>
#include <IO/Operators.h>
Expand Down
18 changes: 14 additions & 4 deletions src/DataTypes/IDataType.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,18 @@ class IDataType : private boost::noncopyable, public std::enable_shared_from_thi
/// Name of data type (examples: UInt64, Array(String)).
String getName() const
{
if (custom_name)
return custom_name->getName();
else
return doGetName();
if (custom_name)
return custom_name->getName();
else
return doGetName();
}

String getPrettyName(size_t indent = 0) const
{
if (custom_name)
return custom_name->getName();
else
return doGetPrettyName(indent);
}

DataTypePtr getPtr() const { return shared_from_this(); }
Expand Down Expand Up @@ -131,6 +139,8 @@ class IDataType : private boost::noncopyable, public std::enable_shared_from_thi
virtual String doGetName() const { return getFamilyName(); }
virtual SerializationPtr doGetDefaultSerialization() const = 0;

virtual String doGetPrettyName(size_t /*indent*/) const { return doGetName(); }

public:
/** Create empty column for corresponding type and default serialization.
*/
Expand Down
15 changes: 11 additions & 4 deletions src/Functions/toTypeName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <Functions/IFunction.h>
#include <Core/Field.h>
#include <DataTypes/DataTypeString.h>
#include <Interpreters/Context.h>


namespace DB
Expand All @@ -15,12 +16,15 @@ namespace
class FunctionToTypeName : public IFunction
{
public:
FunctionToTypeName(bool print_pretty_type_names_) : print_pretty_type_names(print_pretty_type_names_)
{
}

static constexpr auto name = "toTypeName";

static FunctionPtr create(ContextPtr)
static FunctionPtr create(ContextPtr context)
{
return std::make_shared<FunctionToTypeName>();
return std::make_shared<FunctionToTypeName>(context->getSettingsRef().print_pretty_type_names);
}

String getName() const override
Expand Down Expand Up @@ -49,15 +53,18 @@ class FunctionToTypeName : public IFunction

ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
return DataTypeString().createColumnConst(input_rows_count, arguments[0].type->getName());
return DataTypeString().createColumnConst(input_rows_count, print_pretty_type_names ? arguments[0].type->getPrettyName() : arguments[0].type->getName());
}

ColumnPtr getConstantResultForNonConstArguments(const ColumnsWithTypeAndName & arguments, const DataTypePtr &) const override
{
return DataTypeString().createColumnConst(1, arguments[0].type->getName());
return DataTypeString().createColumnConst(1, print_pretty_type_names ? arguments[0].type->getPrettyName() : arguments[0].type->getName());
}

ColumnNumbers getArgumentsThatDontImplyNullableReturnType(size_t /*number_of_arguments*/) const override { return {0}; }

private:
bool print_pretty_type_names;
};

}
Expand Down
4 changes: 4 additions & 0 deletions src/IO/WriteHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,8 @@ void writePointerHex(const void * ptr, WriteBuffer & buf)
buf.write(hex_str, 2 * sizeof(ptr));
}

String fourSpaceIndent(size_t indent)
{
return std::string(indent * 4, ' ');
}
}
2 changes: 2 additions & 0 deletions src/IO/WriteHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,8 @@ struct PcgSerializer

void writePointerHex(const void * ptr, WriteBuffer & buf);

String fourSpaceIndent(size_t indent);

}

template<>
Expand Down
10 changes: 8 additions & 2 deletions src/Interpreters/InterpreterDescribeQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,16 @@ BlockIO InterpreterDescribeQuery::execute()
{
res_columns[0]->insert(column.name);

DataTypePtr type;
if (extend_object_types)
res_columns[1]->insert(storage_snapshot->getConcreteType(column.name)->getName());
type = storage_snapshot->getConcreteType(column.name);
else
res_columns[1]->insert(column.type->getName());
type = column.type;

if (getContext()->getSettingsRef().print_pretty_type_names)
res_columns[1]->insert(type->getPrettyName());
else
res_columns[1]->insert(type->getName());

if (column.default_desc.expression)
{
Expand Down
38 changes: 38 additions & 0 deletions tests/queries/0_stateless/02889_print_pretty_type_names.reference
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
a Tuple(
b String,
c Tuple(
d Nullable(UInt64),
e Array(UInt32),
f Array(Tuple(
g String,
h Map(
String,
Array(Tuple(
i String,
j UInt64
))
)
)),
k Date
),
l Nullable(String)
)
Tuple(
b String,
c Tuple(
d Nullable(UInt64),
e Array(UInt32),
f Array(Tuple(
g String,
h Map(
String,
Array(Tuple(
i String,
j UInt64
))
)
)),
k Date
),
l Nullable(String)
)
5 changes: 5 additions & 0 deletions tests/queries/0_stateless/02889_print_pretty_type_names.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
create table test (a Tuple(b String, c Tuple(d Nullable(UInt64), e Array(UInt32), f Array(Tuple(g String, h Map(String, Array(Tuple(i String, j UInt64))))), k Date), l Nullable(String))) engine=Memory;
insert into test select * from generateRandom(42) limit 1;
set print_pretty_type_names=1;
desc test format TSVRaw;
select toTypeName(a) from test limit 1 format TSVRaw;

0 comments on commit e8d8c6d

Please sign in to comment.