diff --git a/lib/column/map.go b/lib/column/map.go index 79dc75abec..f08056633f 100644 --- a/lib/column/map.go +++ b/lib/column/map.go @@ -169,6 +169,15 @@ func (col *Map) Append(v any) (nulls []uint8, err error) { } func (col *Map) AppendRow(v any) error { + if v == nil { + return &ColumnConverterError{ + Op: "Append", + To: string(col.chType), + From: fmt.Sprintf("%T", v), + Hint: fmt.Sprintf("try using %s", col.scanType), + } + } + value := reflect.Indirect(reflect.ValueOf(v)) if value.Type() == col.scanType { var ( diff --git a/tests/map_test.go b/tests/map_test.go index 51194cbea2..9bd7eac74f 100644 --- a/tests/map_test.go +++ b/tests/map_test.go @@ -338,6 +338,31 @@ func TestOrderedMap(t *testing.T) { require.Equal(t, 1000, i) } +func TestInsertMapNil(t *testing.T) { + conn, err := GetNativeConnection(nil, nil, &clickhouse.Compression{ + Method: clickhouse.CompressionLZ4, + }) + ctx := context.Background() + require.NoError(t, err) + if !CheckMinServerServerVersion(conn, 21, 9, 0) { + t.Skip(fmt.Errorf("unsupported clickhouse version")) + return + } + const ddl = ` + CREATE TABLE test_map_nil ( + Col1 Map(String, UInt64) + ) Engine MergeTree() ORDER BY tuple() + ` + defer func() { + conn.Exec(ctx, "DROP TABLE IF EXISTS test_map_nil") + }() + require.NoError(t, conn.Exec(ctx, ddl)) + batch, err := conn.PrepareBatch(ctx, "INSERT INTO test_map_nil") + require.NoError(t, err) + + assert.ErrorContains(t, batch.Append(nil), " converting to Map(String, UInt64) is unsupported") +} + type testMapSerializer struct { val map[string]uint64 } diff --git a/tests/std/map_test.go b/tests/std/map_test.go index 1b7cee95df..10bd6075c0 100644 --- a/tests/std/map_test.go +++ b/tests/std/map_test.go @@ -98,3 +98,35 @@ func TestStdMap(t *testing.T) { }) } } + +func TestStdInsertNilMap(t *testing.T) { + dsns := map[string]clickhouse.Protocol{"Native": clickhouse.Native, "Http": clickhouse.HTTP} + useSSL, err := strconv.ParseBool(clickhouse_tests.GetEnv("CLICKHOUSE_USE_SSL", "false")) + require.NoError(t, err) + for name, protocol := range dsns { + t.Run(fmt.Sprintf("%s Protocol", name), func(t *testing.T) { + conn, err := GetStdDSNConnection(protocol, useSSL, url.Values{}) + require.NoError(t, err) + if !CheckMinServerVersion(conn, 21, 9, 0) { + t.Skip(fmt.Errorf("unsupported clickhouse version")) + return + } + const ddl = ` + CREATE TABLE test_map_nil ( + Col1 Map(String, UInt64) + ) Engine MergeTree() ORDER BY tuple() + ` + defer func() { + conn.Exec("DROP TABLE test_map_nil") + }() + _, err = conn.Exec(ddl) + require.NoError(t, err) + scope, err := conn.Begin() + require.NoError(t, err) + batch, err := scope.Prepare("INSERT INTO test_map_nil") + require.NoError(t, err) + _, err = batch.Exec(nil) + assert.ErrorContains(t, err, " converting to Map(String, UInt64) is unsupported") + }) + } +}