Fix inserts into tables whose name requires quoting (#602) - #603
Open
polyglotAI-bot wants to merge 1 commit into
Open
Fix inserts into tables whose name requires quoting (#602)#603polyglotAI-bot wants to merge 1 commit into
polyglotAI-bot wants to merge 1 commit into
Conversation
InsertBinaryAsync and InsertRawStreamAsync concatenated the caller's table name into the generated SQL, so a legal ClickHouse name that requires quoting (my-table, user events) failed with SYNTAX_ERROR. Enclose every part of the possibly database-qualified name, and the column names of InsertRawStreamAsync, leaving a part the caller already enclosed as it is. Fixes: #602
polyglotAI-bot
requested review from
alex-clickhouse and
mzitnik
as code owners
August 31, 2026 14:26
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes ClickHouse bulk/raw insert paths to treat the table argument as an identifier (not a SQL fragment) by consistently enclosing table names (including database.table) and raw-stream column names, enabling inserts into tables/columns that require quoting (e.g. my-table, user events, names with backticks).
Changes:
- Added
EncloseQualifiedName()to safely quote qualified identifiers part-by-part while preserving already-quoted input. - Updated schema probe + insert SQL generation to use quoted table names; updated raw-stream inserts to quote column names too.
- Added/updated tests plus docs and changelog fragment to lock in the new identifier-quoting contract.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| docs/overview.mdx | Documents that table/column parameters are treated as names and will be enclosed (qualified names part-by-part). |
| ClickHouse.Driver/Utility/StringExtensions.cs | Introduces EncloseQualifiedName() (splits qualified names safely and encloses each part once). |
| ClickHouse.Driver/Utility/SchemaResolver.cs | Quotes table name in schema probe and normalizes schema cache key to the same quoting behavior. |
| ClickHouse.Driver/ClickHouseClient.cs | Quotes table name in INSERT INTO ... for binary and raw-stream insert paths; quotes raw-stream column list. |
| ClickHouse.Driver.Tests/Utility/StringExtensionsTests.cs | Adds unit tests for qualified-name parsing/quoting and idempotence. |
| ClickHouse.Driver.Tests/SQL/QuotedIdentifierInsertTests.cs | Adds integration tests covering inserts into quoted-required table/column names across affected APIs. |
| ClickHouse.Driver.Tests/InsertBinaryQueryPlacementTests.cs | Updates exact-statement expectations to reflect quoted table names. |
| ClickHouse.Driver.Tests/Copy/InsertBinaryRequestBufferingTests.cs | Updates expected request payload to reflect quoted table names. |
| changelog.d/602-quote-insert-table-name.fixes.md | Adds user-facing changelog entry for the behavior fix. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #602.
The insert paths spliced the caller's
tablestring straight into the generated SQL, so a legal ClickHouse table name that is not a legal unquoted identifier could never be used:FROM my-tableparses asmyminustableand the server answersSYNTAX_ERROR, even though the table exists. The column names on theInsertBinaryAsyncpath already went throughEncloseColumnName()a few lines away, andSchemaResolver.BuildCacheKeyalready enclosed the table name for the cache key — only the name that reached the SQL was left bare.InsertRawStreamAsyncleft its column names bare as well, unlike every other insert path.The fix treats the argument as a name rather than a SQL fragment.
EncloseQualifiedName()splits a possibly database-qualified name on its top-level separators and encloses each part, sodatabase.tablebecomes`database`.`table`. A part the caller already enclosed is returned unchanged, which keeps the documented workaround (pre-quoting the argument) working and makes the operation idempotent — needed because the three sites enclose independently.Changes
ClickHouse.Driver/Utility/StringExtensions.cs: new internalEncloseQualifiedName(). Splits on separators outside an enclosed part (backslash escapes inside one are honored) and encloses each part with the existingEncloseColumnName(). A part enclosed in backticks, or in the double quotes ClickHouse equally accepts around an identifier, is left as it is.ClickHouse.Driver/Utility/SchemaResolver.cs: encloses the table name in theSELECT … WHERE 1=0schema probe, and builds the schema cache key with the same helper, so the bare and pre-quoted spellings of one table no longer occupy two cache entries.ClickHouse.Driver/ClickHouseClient.cs: encloses the table name in theINSERT INTO … FORMAT …statement of both binary insert overloads and ofInsertRawStreamAsync, and enclosesInsertRawStreamAsync's column names.docs/overview.mdx: states the contract for the bulk-insert and raw-stream-insert sections.changelog.d/602-quote-insert-table-name.fixes.md.Test
ClickHouse.Driver.Tests/SQL/QuotedIdentifierInsertTests.csinserts into tables whose names require quoting, against a real server:InsertBinaryAsync, parametrized over three name shapes (hyphen, space, embedded backtick) — covers the schema probe and the INSERT statement. Seven of these cases fail onmainwithSYNTAX_ERROR.InsertBinaryAsyncwithInsertOptions.ColumnTypes, where no probe is sent and the INSERT statement is the only use of the name.InsertRawStreamAsyncwith a name requiring quoting, and with a column name requiring quoting.main; it is the existing workaround) and one in double quotes. Both must be quoted once, not twice.ClickHouse.Driver.Tests/Utility/StringExtensionsTests.cspins the parsing: qualified and unqualified names, a separator inside an enclosed part, backtick escaping, partially enclosed input, and idempotence.Two existing tests assert the generated statement text and were updated to expect the quoted name (
InsertBinaryQueryPlacementTests,Copy/InsertBinaryRequestBufferingTests). Both still assert exact equality; the expectation is spelled out from the database and table name rather than taken from the helper under test.Full suite on net10.0: 10963 passed, 0 failed, 142 skipped.
Compatibility
Callers that pass a table name — including a
database.tablename, and one they pre-quoted themselves — are unaffected. A caller that used the parameter as a SQL fragment (for exampleINSERT INTO FUNCTION …, or an inlined column list) would now have that fragment enclosed as a name. The parameter is documented as a table name, andInsertRawStreamAsynchas a dedicatedcolumnsargument, so this is a deliberate narrowing rather than a supported use.Pre-PR validation gate
main, pass on the branch)AGENTS.md(unique table names, parametrized cases, docs, changelog fragment)