Reject CREATE TABLE ... CLONE AS SELECT / table function#105004
Reject CREATE TABLE ... CLONE AS SELECT / table function#105004tuanpach wants to merge 13 commits into
Conversation
The parser accepted CREATE TABLE t CLONE AS SELECT ... and CREATE TABLE t CLONE AS <table_function>, but neither shape has partitions to attach, so the CLONE keyword was silently ignored and the table was created as a plain CREATE ... AS SELECT. Reject these shapes in getTablePropertiesAndNormalizeCreateQuery with BAD_ARGUMENTS. The check is gated to fresh user CREATE only — pre-fix the AS-table-function shape was persisted into .sql metadata, and rejecting on ATTACH would break loading of any such legacy table on upgrade. Also fix ASTCreateQuery::formatQueryImpl: the `if (select)` branch did not emit CLONE, so an AST round-trip silently dropped the keyword. The randomized-settings injection in clickhouse-test round-trips queries through this formatter, which is how the gap surfaced. Fixes ClickHouse#104994
ae90c08 to
5fb381c
Compare
|
This was fixed by #105146. Let's update the branch. |
The guard added in `getTablePropertiesAndNormalizeCreateQuery` only fired for a fresh `CREATE` (`mode <= CREATE`). A user-supplied full `ATTACH` definition — one that carries an explicit column list (and an engine for the `SELECT` form) — is not the short-attach path: `attach_short_syntax` is false, so it goes through the create-like path with `mode == ATTACH` and bypassed the guard. `isCreateQueryWithImmediateInsertSelect` returns false for `attach` and the clone partition-attach path requires `as_table_saved`, so `CLONE AS SELECT` / `CLONE AS table_function` were silently ignored for such `ATTACH` queries, exactly as they were for `CREATE` before this fix. Extend the guard to also reject `is_clone_as && as_table.empty()` for a user-supplied full `ATTACH` (`mode == ATTACH && !attach_short_syntax`), while leaving short `ATTACH` (`ATTACH TABLE t;`) and `SECONDARY_CREATE` (`DatabaseReplicated` internal queries, `RESTORE`) permissive so previously-validated metadata that persisted these forms still loads. Server startup is unaffected: it loads tables via `createTableFromAST`, which never calls this function. Adds full-`ATTACH` regression cases to `04238_clone_as_select_rejected`. Addresses review feedback on ClickHouse#105004 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Addressed the AI review's "Request changes" verdict (full The guard in The guard now also rejects Added regression cases to |
|
The only red check is AST fuzzer (amd_debug) — The failing query is a fuzzer-mutated This signature has failed 279 times over the last 6 months across ~249 unrelated PRs (e.g. #105714, #106215, #107125, #88234, #86768, #108055, #79091, #109107, #108414). It was tracked by the now-closed #106358 (exact STID All other checks are green and the PR is approved. |
LLVM Coverage ReportChanged lines: Changed C/C++ lines covered: 11/11 (100.00%) · Uncovered code |

The
CREATE TABLE ... CLONE AS <source>clause is intended to clone a real on-disk source table — the partition-attach step performed after table creation needs actual partitions to copy. The parser, however, also acceptedCREATE TABLE t CLONE AS SELECT ...andCREATE TABLE t CLONE AS <table_function>. Neither shape has partitions to attach, so theCLONEkeyword was silently ignored and the table was created as a plainCREATE ... AS SELECTwith an inferred schema andORDER BY tuple().This PR rejects both shapes early in
getTablePropertiesAndNormalizeCreateQuerywithBAD_ARGUMENTS, so the user gets a clear error instead of silent misbehavior. It also fixes a related defect inASTCreateQuery::formatQueryImpl: theif (select)branch did not calladd_clone_if_needed, so an AST format round-trip silently droppedCLONEfromCLONE AS SELECT. The randomized-settings injection inclickhouse-testround-trips queries through this formatter, which is how the gap surfaced.Fixes #104994
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
Fix
CREATE TABLE ... CLONE AS SELECT ...andCREATE TABLE ... CLONE AS <table_function>silently ignoring theCLONEkeyword and creating a plainCREATE ... AS SELECTinstead. These shapes are now rejected withBAD_ARGUMENTS.Documentation entry for user-facing changes
CLONE ASdocumentation, which only describes theCLONE AS <table>form.