From 03ba59fa1caca7699ed6ecbd1f7ba001d47c5ac3 Mon Sep 17 00:00:00 2001 From: Curt Hagenlocher Date: Sun, 10 Dec 2023 16:34:36 -0800 Subject: [PATCH] Normalize map types on creation --- csharp/src/Apache.Arrow/Types/MapType.cs | 48 ++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/csharp/src/Apache.Arrow/Types/MapType.cs b/csharp/src/Apache.Arrow/Types/MapType.cs index 73112c815bfbf..47e0be48f9f78 100644 --- a/csharp/src/Apache.Arrow/Types/MapType.cs +++ b/csharp/src/Apache.Arrow/Types/MapType.cs @@ -13,12 +13,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Collections.Generic; namespace Apache.Arrow.Types { public sealed class MapType : NestedType // MapType = ListType(StructType("key", "value")) { + private const string EntriesKey = "entries"; + private const string KeyKey = "key"; + private const string ValueKey = "value"; + public override ArrowTypeId TypeId => ArrowTypeId.Map; public override string Name => "map"; public readonly bool KeySorted; @@ -28,20 +33,23 @@ public sealed class MapType : NestedType // MapType = ListType(StructType("key", public Field ValueField => KeyValueType.Fields[1]; public MapType(IArrowType key, IArrowType value, bool nullable = true, bool keySorted = false) - : this(new Field("key", key, false), new Field("value", value, nullable), keySorted) + : base(Entries(key, value, nullable)) { + KeySorted = keySorted; } public MapType(Field key, Field value, bool keySorted = false) - : this(new StructType(new List() { key, value }), keySorted) + : base(Entries(key, value)) { + KeySorted = keySorted; } - public MapType(StructType entries, bool keySorted = false) : this(new Field("entries", entries, false), keySorted) + public MapType(StructType entries, bool keySorted = false) : base(Entries(entries)) { + KeySorted = keySorted; } - public MapType(Field entries, bool keySorted = false) : base(entries) + public MapType(Field entries, bool keySorted = false) : base(Entries(entries)) { KeySorted = keySorted; } @@ -54,5 +62,37 @@ public MapType UnsortedKey() return new MapType(Fields[0], keySorted: false); } + + private static Field Entries(IArrowType key, IArrowType value, bool nullable) => + new Field(EntriesKey, NewStruct(new Field(KeyKey, key, false), new Field(ValueKey, value, nullable)), false); + + private static Field Entries(Field key, Field value) => + new Field(EntriesKey, NewStruct(NamedField(KeyKey, key), NamedField(ValueKey, value)), false); + + private static Field Entries(StructType entries) + { + return new Field(EntriesKey, Struct(entries), false); + } + + private static StructType NewStruct(Field key, Field value) => new StructType(new[] { key, value }); + + private static StructType Struct(StructType entries) + { + Field key = NamedField(KeyKey, entries.Fields[0]); + Field value = NamedField(ValueKey, entries.Fields[1]); + return object.ReferenceEquals(key, entries.Fields[0]) && object.ReferenceEquals(value, entries.Fields[1]) ? entries : NewStruct(key, value); + } + + private static Field Entries(Field entries) + { + StructType structType = (StructType)entries.DataType; + StructType adjustedStruct = Struct(structType); + return StringComparer.Ordinal.Equals(entries.Name, EntriesKey) && object.ReferenceEquals(structType, adjustedStruct) ? entries : new Field(EntriesKey, adjustedStruct, false); + } + + private static Field NamedField(string name, Field field) + { + return StringComparer.Ordinal.Equals(name, field.Name) ? field : new Field(name, field.DataType, field.IsNullable, field.Metadata); + } } }