Resolve hive partitioning sample path lazily - #111842
Conversation
Object storage tables with an explicit schema and format no longer list the endpoint on CREATE/ATTACH. The sample path for hive partitioning detection is resolved on the first use of the table instead. An unreachable endpoint used to block CREATE and server startup for the whole S3 retry budget.
|
Workflow [PR], commit [021ec01] Summary: ✅
AI ReviewSummaryThis PR defers hive-partition sample-path resolution for explicit-schema object-storage tables from Findings❌ Blockers
Tests
Final VerdictRequest changes. |
|
|
||
| /// The resolution was deferred because the construction context had `use_hive_partitioning` | ||
| /// enabled. Apply that decision regardless of the settings of the triggering query. | ||
| auto resolution_context = Context::createCopy(query_context); |
There was a problem hiding this comment.
Deferring the resolution to a copy of query_context makes the table's cached hive metadata depend on whichever query happens to touch the table first. This path rebuilds the client with the triggering session and then infers the sample path / hive virtual columns from that session's settings, but hive_partitioning_sample_path_resolved prevents later queries from recomputing it. For non-static object-storage configs that allow per-query credential changes, or even different cast_string_to_date_time_mode / list settings, two sessions can now produce different partition columns or types, yet the first successful one becomes global until restart. This needs a stable construction-time resolution context (or a per-query resolution path) rather than snapshotting the first query's session.
There was a problem hiding this comment.
We could potentially try to avoid double configuration->update call (it will also be called in read() a bit later), but since path sample is resolved only once, we can ignore that.
There was a problem hiding this comment.
Seems there can be a race with StorageObjectStorage::alter which also sets metadata
There was a problem hiding this comment.
Now both of them run under hive_partitioning_resolution_mutex.
There was a problem hiding this comment.
May be makes sense to introduce a setting to make this throw instead of a warning, because it could change query result when user does not expect it. WDYT?
There was a problem hiding this comment.
Good idea, I added a separate throw_on_hive_partitioning_resolution_failure setting enabled by default and disabled with older compatibility.
…partitioning_resolution_failure
| catch (...) | ||
| { | ||
| /// Do not let a restricted session degrade the table state, fail closed like the constructor. | ||
| if (getCurrentExceptionCode() == ErrorCodes::ACCESS_DENIED) |
There was a problem hiding this comment.
Not sure how useful is this, since I'd expect a different error code for object storage related access error, or it is for a different kind of access?
There was a problem hiding this comment.
Indeed, it was incorrect in the first place and not needed now anyway. I removed it.
| /// Set only in the constructor when hive partitioning detection is deferred to the first use. | ||
| bool hive_partitioning_sample_path_deferred = false; | ||
| /// Guarded by the mutex. Stays false on failures, so the resolution is retried per query. | ||
| bool hive_partitioning_sample_path_resolved = false; |
There was a problem hiding this comment.
| bool hive_partitioning_sample_path_resolved = false; | |
| bool hive_partitioning_sample_path_resolved = false TSA_GUARDED_BY(hive_partitioning_resolution_mutex); |
| if (!configuration->isDataLakeConfiguration()) | ||
| { | ||
| /// Called before query analysis, so the hive virtual columns are visible to the triggering query. | ||
| resolveHivePartitioningSamplePathIfDeferred(query_context); |
There was a problem hiding this comment.
The new eager-on-first-query call here makes the first selective read pay an unconditional bucket listing before _path pushdown has a chance to narrow anything. The 03741_s3_glob_table_path_pushdown reference change from 1 4 to 2 4 is exactly this extra S3ListObjects. For large globbed tables that means SELECT ... WHERE _path = ... now does one full list just to discover hive metadata, even when the query never touches hive columns. Can we defer resolution until a query actually needs hive virtuals, or reuse the first read-side iterator instead of issuing a separate getPathSample list?
There was a problem hiding this comment.
The same listing previously happened at CREATE/ATTACH — every server start, every globbed table — so moving it to the first query costs one ListObjectsV2 per storage instance and fewer overall; deferring further isn't possible because the hive columns must exist during identifier resolution, before read().
LLVM Coverage Report
Changed lines: Changed C/C++ lines covered: 83/86 (96.51%) · Uncovered code |
Cherry pick #111842 to 26.3: Resolve hive partitioning sample path lazily
Cherry pick #111842 to 26.5: Resolve hive partitioning sample path lazily
Cherry pick #111842 to 26.6: Resolve hive partitioning sample path lazily
Backport #111842 to 26.7: Resolve hive partitioning sample path lazily
Backport #111842 to 26.6: Resolve hive partitioning sample path lazily
Backport #111842 to 26.3: Resolve hive partitioning sample path lazily
Backport #111842 to 26.5: Resolve hive partitioning sample path lazily
Object storage tables with an explicit schema and format no longer list the endpoint on
CREATE/ATTACH— the hive partitioning sample path is resolved on the first use of the table. An unreachable endpoint used to blockCREATEand server startup for hours.Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
The hive partitioning sample path for object storage tables (e.g.
S3) is resolved on the first use of the table instead ofCREATE/ATTACH, so an unreachable endpoint no longer blocks table creation and server startup.Version info
26.8.1.682(included in26.8and later)26.7.4.54,26.6.3.57,26.5.7.61,26.3.20.2