Skip to content

EnumVectorDataWriter throws InvalidOperationException if given an enum with non-consecutive values. #330

@MrZoraman

Description

@MrZoraman

Minimal code reproduction:

using DuckDB.NET.Data;

enum Mood : byte
{
    Happy = 1,
    Sad = 2,
    // Skip 3
    Neutral = 4
}

internal static class Program
{
    private static void Main()
    {
        var enumNames = Enum.GetNames<Mood>();
        var enumLabelsSql = string.Join(", ", enumNames.Select(n => $"'{n}'"));
        var enumTypeSql = $"CREATE TYPE Mood AS ENUM ({enumLabelsSql});";

        using var connection = new DuckDBConnection("Data Source=:memory:");
        connection.Open();

        using var command = connection.CreateCommand();

        command.CommandText = enumTypeSql;
        command.ExecuteNonQuery();

        command.CommandText = "CREATE TABLE EnumTest (Value Mood);";
        command.ExecuteNonQuery();

        var valuesToInsert = new[]
        {
            Mood.Happy,
            Mood.Sad,
            Mood.Neutral
        };

        using (var appender = connection.CreateAppender("EnumTest"))
        {
            foreach (var enumValue in valuesToInsert)
            {
                var row = appender.CreateRow();
                row.AppendValue(enumValue);
                row.EndRow();
            }
        }
    }
}

I believe this is because DuckDB.NET casts the enum to an integer value and then writes that to the database. As long as the enum values are consecutive, DuckDB's internal enum map and C#'s enum map align, so this works out. When the C# enum has gaps in its values, this assumption is no longer true and the code crashes.

This also means that [Flags] enums can cause a bit of chaos as well. Since DuckDB enums aren't designed to be used as flags, DuckDB.NET should probably prevent [Flags] enums from being used entirely, because something like "Happy | Neutral" cannot convert to a DuckDB enum.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions