Skip to content

Reading LowCardinality(Nullable(String)) column is not supported (for the data received from ClickHouse) #504

@rklepov

Description

@rklepov

Please see #339

This one confirms that it works

Perhaps, it would be helpful to know the real type of column at run-time with:

column->GetType().GetName()

Originally posted by @Enmk in #326

The test Map_LowCardinalityTString_LowCardinalityTNullableString might succeed, but this is only true because you create the column with the type ColumnLowCardinalityT<ColumnNullableT<ColumnString>> explicitly in the test.

However, for the real data received from ClickHouse the type of the underlying column will be simply ColumnLowCardinality. This is probably due to the logic implemented in #182:

case Type::Nullable:
    return std::make_shared<ColumnLowCardinality>(
        std::make_shared<ColumnNullable>(
            CreateColumnFromAst(GetASTChildElement(nested, 0), settings),
            std::make_shared<ColumnUInt8>()
        )
    );

Therefore the dynamic_cast inside column->As<ColumnLowCardinalityT<ColumnNullableT<ColumnString>>>() will yield nullptr.

This is easily illustrated with a simple typeid check (assume that column is an instance of a ColumnRef pointer).

This is what we have for LowCardinality(String) column:

// ColumnRef column;

auto type_name = column->GetType().GetName(); // "LowCardinality(String)"

auto type_id = typeid(*column).name(); // clickhouse::ColumnLowCardinalityT<clickhouse::ColumnString> ("N10clickhouse21ColumnLowCardinalityTINS_12ColumnStringEEE")

And this is the result for LowCardinality(Nullable(String)):

// ColumnRef column;

auto type_name = column->GetType().GetName(); // "LowCardinality(Nullable(String))"

auto type_id = typeid(*column).name(); // clickhouse::ColumnLowCardinality ("N10clickhouse20ColumnLowCardinalityE")

The conclusion is that it's not possible to read LowCardinality(Nullable(String)) column in the current version of clickhouse-cpp (v2.6.1):

  1. column->As<ColumnLowCardinalityT<ColumnNullableT<ColumnString>>>() doesn't work for the reasons explained above.
  2. While column->As<ColumnLowCardinality>() does work, it's of no help: trying to wrap the result into ColumnLowCardinalityT<ColumnNullableT<ColumnString>> will also fail because the nested type is ColumnNullable (not ColumnNullableT<ColumnString>).
  3. Declaring ColumnLowCardinalityT<ColumnNullable> is not possible because there's no ValueType alias in ColumnNullable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions