Reading SimpleAggregateFunction inside a Dynamic column throws NotImplementedException

Open Beginner friendly
#505 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
88/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
csharp
Domain
databases

Research direction

Start in ClickHouse.Driver/Types/BinaryTypeDecoder.cs at DecodeSimpleAggregateFunction and inspect the FromByteCode path, then run the supplied ShouldReadSimpleAggregateFunctionInDynamic reproduction. Compare it with SimpleAggregateFunctionType.Parse and the top-level passing test; done means the Dynamic read returns 42UL and the following tail value remains readable.

Written by the indexing model from the issue text.

Description

Description

The server keeps SimpleAggregateFunction(func, T) as a concrete Dynamic subtype and encodes it in the binary type encoding as:

0x2E <function_name> <var_uint number_of_parameters><parameters> <var_uint number_of_arguments><argument_type_encodings>

BinaryTypeDecoder.FromByteCode dispatches BinaryTypeIndex.SimpleAggregateFunction (0x2E) to DecodeSimpleAggregateFunction, which is an unimplemented stub:

// ClickHouse.Driver/Types/BinaryTypeDecoder.cs:300
private static SimpleAggregateFunctionType DecodeSimpleAggregateFunction(ExtendedBinaryReader reader)
{
    throw new NotImplementedException("SimpleAggregateFunction decoding not implemented.");
}

So reading a SimpleAggregateFunction value out of a Dynamic column throws and the query fails. The same FromByteCode path is used by VariantType, JsonType and nested Dynamic, so those are affected too.

Note that a top-level SimpleAggregateFunction column works fine — that path goes through the textual type-name grammar (SimpleAggregateFunctionType.Parse), not the binary decoder. Only the binary-type-encoding path is broken.

Related: DecodeAggregateFunction (0x1E) is the same kind of stub at BinaryTypeDecoder.cs:295.

ClickHouse server version

26.7.2.59 (verified against a running server)

Reproduction

using ClickHouse.Driver.Utility;

public class SafDynamicTests : AbstractConnectionTestFixture
{
    [Test]
    public async Task ShouldReadSimpleAggregateFunctionInDynamic()
    {
        using var reader = await connection.ExecuteReaderAsync(
            "SELECT CAST(CAST(42, 'SimpleAggregateFunction(sum, UInt64)') AS Dynamic) AS d, 42::Int32 AS tail");
        Assert.That(reader.Read(), Is.True);
        Assert.That(reader.GetValue(0), Is.EqualTo((ulong)42));
        Assert.That(reader.GetValue(1), Is.EqualTo(42));
    }

    [Test]  // this one passes today (textual type-name path)
    public async Task ShouldReadTopLevelSimpleAggregateFunction()
    {
        using var reader = await connection.ExecuteReaderAsync(
            "SELECT CAST(42, 'SimpleAggregateFunction(sum, UInt64)') AS d, 42::Int32 AS tail");
        Assert.That(reader.Read(), Is.True);
        Assert.That(reader.GetValue(0), Is.EqualTo((ulong)42));
        Assert.That(reader.GetValue(1), Is.EqualTo(42));
    }
}

Expected: both tests pass, d reads as 42UL and tail as 42.

Actual: ShouldReadTopLevelSimpleAggregateFunction passes, ShouldReadSimpleAggregateFunctionInDynamic fails:

Failed ShouldReadSimpleAggregateFunctionInDynamic [17 ms]
  System.NotImplementedException : SimpleAggregateFunction decoding not implemented.
   at ClickHouse.Driver.Types.BinaryTypeDecoder.DecodeSimpleAggregateFunction(ExtendedBinaryReader reader) in ClickHouse.Driver/Types/BinaryTypeDecoder.cs:line 302
   at ClickHouse.Driver.Types.BinaryTypeDecoder.FromByteCode(ExtendedBinaryReader reader, TypeSettings typeSettings) in ClickHouse.Driver/Types/BinaryTypeDecoder.cs:line 176
   at ClickHouse.Driver.Types.DynamicType.Read(ExtendedBinaryReader reader) in ClickHouse.Driver/Types/DynamicType.cs:line 21
   at ClickHouse.Driver.ADO.Readers.ClickHouseDataReader.Read() in ClickHouse.Driver/ADO/Readers/ClickHouseDataReader.cs:line 458

Suggested fix

Implement DecodeSimpleAggregateFunction in ClickHouse.Driver/Types/BinaryTypeDecoder.cs:300 to consume the full encoding and return a usable type:

  1. reader.ReadString() — function name
  2. reader.Read7BitEncodedInt() parameters, each a field-value encoding — must be consumed even when ignored
  3. reader.Read7BitEncodedInt() arguments, each FromByteCode(reader, typeSettings)

Return new SimpleAggregateFunctionType { AggregateFunction = name, UnderlyingType = arguments[0] } (its Read already delegates to the underlying type). Consuming the whole encoding matters independently of the exception: if the tag were skipped without consuming the payload, the function name and argument encodings would be interpreted as row data and desynchronize the rest of the RowBinary stream. Note the signature needs TypeSettings threaded in to decode argument types.

Nothing (0x00) parameters aside, ClickHouse currently only emits parameterized SimpleAggregateFunction for a few functions, but the parameter section must still be skipped correctly.

Link

Relayed from https://github.com/ClickHouse/clickhouse-java/issues/3005

Dominant language
C#
Stars
94
Forks
22
Avg merge
9h 32m
Merged PRs (30d)
14

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ClickHouse/clickhouse-cs

All issues in ClickHouse/clickhouse-cs

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.