diff --git a/lib/column/json.go b/lib/column/json.go index ca9120668e..1c11c3b1bd 100644 --- a/lib/column/json.go +++ b/lib/column/json.go @@ -501,6 +501,21 @@ func appendStructOrMap(jCol *JSONObject, data any) error { Err: fmt.Errorf("map keys must be string for column %s", jCol.Name()), } } + + if vData.Len() == 0 { + // if map is empty, we need to create an empty Tuple to make sure subcolumns protocol is happy + // _dummy is a ClickHouse internal name for empty Tuple subcolumn + // it has the same effect as `INSERT INTO single_json_type_table VALUES ('{}');` + emptyVal := &JSONValue{Interface: &UInt8{name: "_dummy"}} + if err := emptyVal.appendEmptyValue(); err != nil { + return err + } + jCol.columns = []JSON{ + emptyVal, + } + return nil + } + return iterateMap(vData, jCol, 0) } return &UnsupportedColumnTypeError{ diff --git a/tests/issues/1113_test.go b/tests/issues/1113_test.go new file mode 100644 index 0000000000..2de26ccfee --- /dev/null +++ b/tests/issues/1113_test.go @@ -0,0 +1,38 @@ +package issues + +import ( + "context" + "github.com/ClickHouse/clickhouse-go/v2" + clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests" + "github.com/stretchr/testify/require" + "testing" +) + +func Test1113(t *testing.T) { + var ( + conn, err = clickhouse_tests.GetConnection("issues", clickhouse.Settings{ + "max_execution_time": 60, + "allow_experimental_object_type": true, + }, nil, &clickhouse.Compression{ + Method: clickhouse.CompressionLZ4, + }) + ) + ctx := context.Background() + require.NoError(t, err) + const ddl = "CREATE TABLE test_1113 (col_1 JSON, col_2 JSON) Engine MergeTree() ORDER BY tuple()" + require.NoError(t, conn.Exec(ctx, ddl)) + defer func() { + conn.Exec(ctx, "DROP TABLE IF EXISTS test_1113") + }() + + batch, err := conn.PrepareBatch(context.Background(), "INSERT INTO test_1113") + require.NoError(t, err) + + v1 := map[string]struct { + Str string + }{"a": {Str: "value"}} + v2 := map[string]any{} + + require.NoError(t, batch.Append(v1, v2)) + require.NoError(t, batch.Send()) +}