ClickHouse / ClickHouse/clickhouse-go
JSON typed path containing a space is unparseable: unsupported column type "b` Int64"
- Dominant language
- Go
- Stars
- 3.3k
- Forks
- 680
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 14
Description
### Describe the bug
ClickHouse allows a `JSON` typed path name to contain characters that require backtick quoting, e.g. a space. The server accepts, stores and round-trips `JSON(`a b` Int64)` fine, but this driver cannot parse the column type at all, so **the whole query fails** — not just the offending path.
In `lib/column/json.go`, `(*JSON).parse` splits each type part on the **first** space:
https://github.com/ClickHouse/clickhouse-go/blob/main/lib/column/json.go#L137-L143
```go
typedPathParts := strings.SplitN(typePart, " ", 2)
if len(typedPathParts) != 2 {
continue
}
typedPath := strings.Trim(typedPathParts[0], "`")
typeName := strings.TrimSpace(typedPathParts[1])
```
For the type part `` `a b` Int64 `` this yields `typedPath = "a"` and `typeName = "b` Int64"`, and the subsequent `Type(typeName).Column(...)` call fails.
Note that the sibling helper `splitWithDelimiters` (json.go:1084) *is* backtick-aware, so the comma case (`` JSON(`a,b` Int64) ``) works correctly — only the space split is wrong. Dotted paths are fine too (both sides treat `.` as a nesting separator).
### ClickHouse server version
Code analysis plus a driver-side unit test; no ClickHouse server was reachable in this environment, so this was not verified end-to-end against a live server. The type strings used in the test are the forms the server emits (as reported in the linked upstream issue, measured against ClickHouse 26.6.1).
### Reproduction
Drop this into `lib/column/` and run `go test ./lib/column/ -run TestJSONPathWithSpace -v`:
```go
package column
import "testing"
func TestJSONPathWithSpace(t *testing.T) {
types := []string{
"JSON(`a b` Int64)",
"JSON(`a b` Decimal(10, 2))",
"JSON(`a,b` Int64)",
"JSON(`a.b` Int64)",
}
for _, tStr := range types {
col, err := Type(tStr).Column("x", nil)
if err != nil {
t.Errorf("%s -> ERROR %v", tStr, err)
continue
}
t.Logf("%s -> typedPaths=%v", tStr, col.(*JSON).typedPaths)
}
}
```
**Expected:** all four parse, with `typedPaths` of `[a b]`, `[a b]`, `[a,b]`, `[a.b]`.
**Actual** (run on `main`):
```
json_space_test.go:15: JSON(`a b` Int64) -> ERROR failed to init column of type "b` Int64" at path "a": clickhouse: unsupported column type "b` Int64"
json_space_test.go:15: JSON(`a b` Decimal(10, 2)) -> ERROR failed to init column of type "b` Decimal(10, 2)" at path "a": clickhouse: unsupported column type "b` Decimal(10, 2)"
json_space_test.go:19: JSON(`a,b` Int64) -> typedPaths=[a,b]
json_space_test.go:19: JSON(`a.b` Int64) -> typedPaths=[a.b]
--- FAIL: TestJSONPathWithSpace (0.00s)
```
The equivalent end-to-end usage that would hit this:
```sql
CREATE TABLE t (data JSON(`a b` Int64)) ENGINE = Memory;
INSERT INTO t VALUES ('{"a b": 1}');
```
```go
rows, err := conn.Query(ctx, "SELECT data FROM t")
// column-type parsing of the response header fails, so Query itself errors
```
Also note the path is silently mis-registered as `"a"` before the type parse fails, so any future leniency here would need to fix both halves.
### Suggested fix
`lib/column/json.go:137` — split the typed-path part on the **last** space that is outside backticks, rather than on the first space, mirroring the backtick awareness already present in `splitWithDelimiters`. The path is already `strings.Trim(..., "`")`-ed on the next line, so backtick-quoted names are clearly intended to be supported here.
### Link
Relayed from ClickHouse/clickhouse-cs#502 (same root cause, different split bug: the C# driver splits on *every* space).
Contributor guide
Research direction
Start in lib/column/json.go at (*JSON).parse around lines 137-143, then compare its typed-path splitting with the backtick-aware splitWithDelimiters helper. Add or run the lib/column TestJSONPathWithSpace reproduction and confirm that JSON paths containing spaces, decimals, commas, and dots all parse with the complete path preserved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100