Repository navigation
Fix bugs in dropping partition columns - #281
jiang95-dev wants to merge 9 commits into
Conversation
* API: Add `UnknownType` * Make the CI happy * Thanks Eduard! * Add tests for the other transforms as well * Thanks Honah! * Thanks Russell! * Thanks Eduard! (cherry picked from commit a04220a) Backport note: conflicting files temporarily use upstream versions; 1.5.2 compatibility is restored in the final adaptation commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 3c8366a) Backport note: conflicting files temporarily use upstream versions; 1.5.2 compatibility is restored in the final adaptation commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…urrent-schema (#11868) Co-authored-by: Nynke Gaikema <nynkegaikema@MacBook-Air-van-Nynke.local> (cherry picked from commit 8134815) Backport note: conflicting files temporarily use upstream versions; 1.5.2 compatibility is restored in the final adaptation commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…13301) (cherry picked from commit 867835e) Backport note: conflicting files temporarily use upstream versions; 1.5.2 compatibility is restored in the final adaptation commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit c22bac8) Backport note: conflicting files temporarily use upstream versions; 1.5.2 compatibility is restored in the final adaptation commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ing mode (#16523) (cherry picked from commit 4057f59dbee6878b3986f7cc39b1f30a59ee9ee3) Backport note: conflicting files temporarily use upstream versions; 1.5.2 compatibility is restored in the final adaptation commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…wn (#17262) PartitionSpec.partitionType() degrades a partition field's type to `unknown` whenever the source column has been dropped from the schema, even for transforms like bucket and the date/time transforms whose result type does not depend on the source type. Substitute unknown as the source type instead and let the transform derive its result type, matching the existing behavior of javaClasses(). Identity and truncate still fall back to unknown because their result type is the source type. Follow-up to the discussion in apache/iceberg#16958 (comment) (cherry picked from commit e973bc0fcd05514466fd0e201c34ece2b396c4fd) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve the cross-version conflicts deferred by the preceding upstream commits. Keep the UnknownType and Avro support needed by the partition fixes without importing unrelated timestamp-nanosecond/variant features, newer reader APIs, Spark 4.x modules, or migrated test infrastructure. Preserve the 1.5.2 implementation and local default-value behavior. Adapt the upstream time-travel planner fixes to Spark 3.4 as well as 3.5. Add RTAS/drop-source read and append tests, historical predicates in LOCAL and DISTRIBUTED planning modes, ordinary ALTER/drop-source/DELETE coverage, and core partition/schema-evolution regressions. Upstream PRs: apache/iceberg#12012, #12455, #11868, #13301, #14356, #16523, #17262. Intermediate commits intentionally retain incoming versions of conflicting files and need not compile individually; this commit restores the validated final tree. Validation: API suite, targeted core partition/parser/Avro/schema-evolution tests, Spark 3.4 compilation, Spark 3.5 CTAS/RTAS suite and ALTER/drop-source/DELETE tests, plus formatting checks. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
mkuchenbecker
left a comment
There was a problem hiding this comment.
This backport seems overly broad without further explanation and the changes to make it work are 30% of the total lines shanged.
Its pulling in variant and other code. it seems the issue is more localized; is there a smaller change that could be made? the core issue seems to be loading the old column data but I may be underestimateing
This seems like a bug to give a stacktrace when a deterministic error is sufficent. |
I'm not sure if it is a github rendering bug. The PR did not add variant or timestampNano support. The final commit cut all the unrelated changes. Can you take a look again? Also I've added in the PR description the explanations to the 7 commits, and also what are the core changes in the last commit. |
Are you saying we should change the way we surface this disallowed operation? Like throwing "spec mismatch the current schema"? |
| return sanitizeTimestamp(DateTimeUtil.nanosToMicros((long) value / 1000), now); | ||
| case STRING: | ||
| return sanitizeString((CharSequence) value, now, today); | ||
| case UNKNOWN: |
There was a problem hiding this comment.
Unkonwn should be handled here, no?
|
|
||
| private static String sanitizeSimpleString(CharSequence value) { | ||
| // hash the value and return the hash as hex | ||
| return String.format(Locale.ROOT, "(hash-%08x)", HASH_FUNC.apply(value)); |
There was a problem hiding this comment.
why did se change the format string from the backport?
| variantValue.writeTo(variantBuffer, variantMetadata.sizeInBytes()); | ||
| return variantBuffer; | ||
| case UNKNOWN: | ||
| // underlying type not known |
There was a problem hiding this comment.
why is the comment on unknown removed?
| case VARIANT: | ||
| return Variant.from(tmp); | ||
| case UNKNOWN: | ||
| // underlying type not known |
| @Override | ||
| public String toString() { | ||
| return String.format(Locale.ROOT, "fixed[%d]", length); | ||
| return String.format("fixed[%d]", length); |
There was a problem hiding this comment.
unclear why this was changed from backport
| private boolean isOptional = true; | ||
| private String name = null; |
| return visit(schema, new FindTypeVisitor(predicate)); | ||
| } | ||
|
|
||
| public static Type find(Type type, Predicate<Type> predicate) { |
There was a problem hiding this comment.
Why are we removing the visitor?
| Types.NestedField sourceColumn = findSourceColumn(sourceName); | ||
| String columnName = schema.findColumnName(sourceColumn.fieldId()); | ||
| return day(sourceColumn, columnName + "_day"); | ||
| return day(sourceName, sourceName + "_day"); |
There was a problem hiding this comment.
I don't understand why we are removing the source column resolution. Can we explain?
| assertThat(identity.toHumanString(timestamptz, ts.value())) | ||
| .as("Should produce timestamp with time zone adjusted to UTC") | ||
| .isEqualTo("2017-12-01T18:12:55.038194+00:00"); | ||
| .isEqualTo("2017-12-01T18:12:55.038194Z"); |
There was a problem hiding this comment.
why is this different than OSS? TZ precision change?
Problem statement
Running RTAS to drop a partition column will cause
"Cannot find source column for partition field". This is because when iceberg constructsSerializableTable, it binds all historical partition specs with the current schema, and throws an error when the spec contains missing columns. RTAS should be an atomic operation that supports dropping any columns without needing to drop the partition spec first.Note, in the current branch, even in the regular path, dropping the column after dropping the partition field will fail.
Out of scope
In the normal drop partition column path, it also failed but the failure is an expected behavior.
TableMetadatachecks if the current spec is compatible with the current schema. It is not a bug and this PR is not fixing this.Changes
This bug has already been fixed in the upstream. This PR backports 7 related upstream PRs, fixes the merge conflicts, and adds RTAS related tests to verify the fix. Note this PR is not a backport PR but borrows the idea from the upstream fix.
The main idea is to use
UnknownTypewhen a partition source column is missing from the current schema, and let the transform determine the result type. Identity and truncate resolve toUnknownType, while transforms with fixed result types, such as bucket, retain their known types.For time-travel reads, partition specs are rebound to the selected snapshot’s schema so predicates on historical columns can be resolved correctly.
Backport commits explanation
99f1c0b03— apache/iceberg#12012UnknownType.d7bd0c974— apache/iceberg#12455UnknownTypeneeds an Avro representation. Only the unknown/null conversion and optionality changes are retained; timestamp-nanosecond support is excluded.4f350f540— apache/iceberg#11868SerializableTable.specs()failure. It permits missing source columns during JSON parsing and excludes inactive fields from the current table’s unified partition type.a6868412c— apache/iceberg#13301WHERE dropped_column = ....61a97c3c7— apache/iceberg#14356fdc803d9b— apache/iceberg#1652371256790d— apache/iceberg#17262What the final adaptation commit retains
36c1cb5ea— Adapt upstream partition fixes to Iceberg 1.5.2 and add RTAS regressionsThe final commit resolves cross-version conflicts and leaves the following core changes in the resulting branch:
Minimal
UnknownTypesupport: type definition, type ID, primitive-name parsing, size estimation, and serialization coverage.Historical spec parsing:
PartitionSpecParserallows missing source fields when reconstructing specs. Normal strict spec construction remains available; missing-field tolerance does not make an invalid current partition spec valid.Transform-aware partition types: missing source types become
UnknownType; identity/truncate propagate unknown, while fixed-result transforms retain their known result types.Current partition metadata: fields whose source columns no longer exist are excluded from the current table’s unified partition type.
Avro and delete-path compatibility: unknown/null schema conversion, optionality, comparators, byte-buffer conversions, null writing, and conservative manifest-summary handling.
Time-travel schema binding: local and distributed scan paths use specs rebound to the selected snapshot’s schema, including executor-side manifest readers. The distributed changes are adapted to Spark 3.4 as well as 3.5.
Regression coverage: RTAS source-column removal, subsequent reads/appends, historical reads and filters in LOCAL/DISTRIBUTED planning modes, ordinary partition-field/source-column removal followed by DELETE, and core type/schema-evolution checks.
The final tree does not introduce variant support, timestamp-nanosecond support, Spark 4.x modules, or the custom historical-type recovery implementation. Those unrelated newer-version changes appeared temporarily in intermediate conflict resolutions and were removed by the final adaptation commit.
Testing Done
Added a test in
TestCreateTableAsSelectto test that RTAS can drop a partition column, and still be able to read, and do filtering in time travel.