ClickHouse / ClickHouse/ClickHouse

`parseOptions` copy-paste error maps TSV format to `ASTCopyQuery::Formats::CSV` at line 146

Open
#102,483 0 comments 0 reactions 1 assignee Claimed by @evillique View on GitHub
bug comp-postgresql comp-sql-syntax
Dominant language
C++
Stars
49.9k
Forks
9k
Avg merge
21h 32m
Merged PRs (30d)
515

Description

_Found via ClickGap automated review. Please close or comment if this is incorrect or needs adjustment._

_Retrospective finding from a historical scan of [PR #74344](https://github.com/ClickHouse/ClickHouse/pull/74344) (merged 2025-08-12). Confirmed on current codebase — close with a note if already fixed._

### Describe what's wrong

PostgreSQL COPY commands with explicit `FORMAT tsv` produce CSV output (comma-separated with quoted strings) instead of TSV output (tab-separated). COPY FROM with FORMAT tsv rejects tab-separated input expecting commas.

**Root cause:** ParserCopyQuery.cpp:146: `node->format = ASTCopyQuery::Formats::CSV;` is a copy-paste error from line 144. Should be `ASTCopyQuery::Formats::TSV`. Additionally, lines 141-142 compute a lowercased `format_name` variable but all comparisons on lines 143-148 use the original `full_name`, making format names case-sensitive (uppercase FORMAT TSV throws BAD_ARGUMENTS).

**Why we believe this is a bug:** PostgreSQLHandler::processCopyQuery (PostgreSQLHandler.cpp:423) → parses query via ParserCopyQuery → parseOptions (ParserCopyQuery.cpp:122) → format comparison at line 145-146 maps "tsv" to `ASTCopyQuery::Formats::CSV` → handler's switch/toString converts to "CSV" format string → FormatFactory produces CSV output

**Affected locations:**
- `src/Parsers/ParserCopyQuery.cpp:146` — TSV format maps to Formats::CSV instead of Formats::TSV
- `src/Parsers/ParserCopyQuery.cpp:141` — format_name lowercased but never used for comparison

**Impact:** Any PostgreSQL client using COPY with explicit FORMAT tsv gets CSV data instead of TSV, causing data corruption on round-trips. COPY FROM with FORMAT tsv rejects valid TSV input with parse errors.

### Does it reproduce on most recent release?

Yes — confirmed on current `master` (commit `9678bc3a5d5e`).

### How to reproduce

```sql
Connect to ClickHouse via PostgreSQL protocol with psycopg2. Create table: CREATE TABLE t (x UInt32, y String) ENGINE=Memory(). Insert: INSERT INTO t VALUES (1,'a'). Run: cur.copy_expert('COPY t TO STDOUT WITH FORMAT tsv', f). Output will have commas instead of tabs.
```

### Expected behavior

```
COPY TO STDOUT WITH FORMAT tsv should produce: '1\thello\n2\tworld\n' (TSV with tabs, no quoting). COPY FROM STDIN WITH FORMAT tsv should successfully parse tab-separated data.
```

### Error message and/or stacktrace

```
COPY TO STDOUT WITH FORMAT tsv produces: '1,"hello"\n2,"world"\n' (CSV with commas and quoted strings). COPY FROM STDIN WITH FORMAT tsv with TSV data fails with: 'Cannot parse input: expected ',' before: 'hello\n20\tworld\n'
```

### Additional context

**Open risks:**
- The secondary case-sensitivity bug means FORMAT TSV, FORMAT Tsv, etc. all fail with BAD_ARGUMENTS exception

**Suggested fix:** Change line 146 to `node->format = ASTCopyQuery::Formats::TSV;`. Also change comparisons on lines 143-148 to use `format_name` (the lowercased variable) instead of `format->as()->full_name` to make format names case-insensitive.

**Analysis details:** Confidence HIGH | Severity P1 | Testability: `INTEGRATION_TEST`

Found during automated review of [PR #74344](https://github.com/ClickHouse/ClickHouse/pull/74344).

---
_ClickGapAI · Confidence: HIGH · Severity: P1 · Finding: `h_pr74344_001`_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.