Summary
extractArrowValue in server/flight_executor.go returns map[string]interface{} for Arrow MAP arrays. All map keys are coerced to strings via fmt.Sprintf("%v", k), regardless of their actual Arrow type.
This works today because conn.go:formatMapValue accepts map[string]any and the PG text protocol is all strings anyway. But it means:
- Key type information is lost (an
int32 key 1 becomes the string "1")
- Round-tripping MAP values back through DuckDB may produce incorrect types
- Binary PG format support would need the original typed keys
Current behavior
// flight_executor.go extractArrowValue, MAP case
m[fmt.Sprintf("%v", k)] = v
A MAP(INTEGER, VARCHAR) with entries {1: "one", 2: "two"} becomes map[string]any{"1": "one", "2": "two"}.
Expected behavior
Preserve typed keys, e.g. return a []MapEntry{{Key: int32(1), Value: "one"}, ...} or similar ordered structure that retains:
- Original key types
- Insertion order (DuckDB MAPs are ordered)
Context
This was noted while fixing the STRUCT/MAP control-plane deserialization bug (STRUCT and MAP cases were missing entirely from extractArrowValue and arrowTypeToDuckDB). The string-key approach was chosen deliberately to match the existing formatMapValue(map[string]any) consumer in conn.go, but it's a known limitation.
Summary
extractArrowValueinserver/flight_executor.goreturnsmap[string]interface{}for Arrow MAP arrays. All map keys are coerced to strings viafmt.Sprintf("%v", k), regardless of their actual Arrow type.This works today because
conn.go:formatMapValueacceptsmap[string]anyand the PG text protocol is all strings anyway. But it means:int32key1becomes the string"1")Current behavior
A
MAP(INTEGER, VARCHAR)with entries{1: "one", 2: "two"}becomesmap[string]any{"1": "one", "2": "two"}.Expected behavior
Preserve typed keys, e.g. return a
[]MapEntry{{Key: int32(1), Value: "one"}, ...}or similar ordered structure that retains:Context
This was noted while fixing the STRUCT/MAP control-plane deserialization bug (STRUCT and MAP cases were missing entirely from
extractArrowValueandarrowTypeToDuckDB). The string-key approach was chosen deliberately to match the existingformatMapValue(map[string]any)consumer inconn.go, but it's a known limitation.