Skip to content

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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