Repository navigation
feat(table): unify index options and maintain PK/global indexes - #1264
Merged
Merged
Conversation
Rebuild incompatible DE scalar and full-text runs using actual builder-schema provenance and parsed analyzer options. Check vector dimensions alongside algorithms and metrics before reusing coverage. Project PK indexed fields and apply vector deletion masks before schema casts, preserving source ordinals with bounded null batches. Reject publication when concurrent deletion-vector changes restore positions omitted by a new payload. Add reproducing schema, analyzer, dimension, projection, ordinal and concurrent deletion regressions, and document the maintenance contracts.
Share CoreOptions declaration and field-JSON resolution between PK and append/Data Evolution indexes, following apache/paimon#10914. Retain legacy PK and Rust aliases alongside DLF singular declarations and flat parameters. Apply effective field options to native construction, compaction, indexed and raw reads, query widths and refinement. Preserve table-mode routing and PK's compaction-only index lifecycle. Share read caches by budget across fields. Cover precedence, insertion order, invalid defaults, schema guards, native build/read consistency, shard overrides and recovery with regression tests.
Align PK/DE option resolution with Java PR #10914 and remove the four query implementation hint aliases. Preserve canonical, singular, legacy PK and DLF configuration, including replacement field JSON and short parameter keys. Carry per-column explicit implementations through Rust/Python single, batch and hybrid builders, captured scans/readers, raw source plans and workers. Use persisted metadata first, and use the explicit type only for raw fallback. Preserve Java PK metric behavior and eager query validation. Cover native fallback scores, metadata and empty-marker precedence, captured routes/readers, transport round trips, aliases and short JSON parameters.
Keep PK-specific CoreOptions convenience accessors crate-internal and route public callers through the shared global/vector index option APIs. Resolve a legacy vector field type only when pk-vector.index.columns names that column. Preserve complete old configurations and canonical precedence, and retain the native explicit-type API and logical VectorType. Document the compatibility-only boundary and cover orphan field keys, complete declarations and raw fallback scoring.
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.
Purpose
PK compaction previously rejected source-backed index manifests or rewrote data without maintaining declared indexes. DE automatic indexing rebuilt a growing tail shard on each small append, and the two table modes used separate configuration namespaces. Share index configuration across PK and append/DE tables, maintain PK indexes with compacted data, and build DE additions independently until a shared UniversalCompaction policy selects adjacent runs to rebuild.
Changes
CoreOptionsdeclaration and field-option resolution across PK and append/DE construction, maintenance, scans, indexed/raw searches and refinement, following Java PR #10914 at merged commitb4342332(shared resolver, PK payload selection, and lossless Native option forwarding); the resolver and Native build contract also match current upstream master. Useglobal-index.<type>.index-columnsandfields.<column>.index-options, with short field JSON keys such asnlist/dimensionand the existing type-level prefixes such asivf-pq.dimension; support the DLF singularindex-columnalias, implementation parameters and flat vector field parameters. Retain legacy PK declarations/options and the former Rust family-style vector configuration. Shared JSON replaces legacy JSON and overrides defaults; non-metric legacy conflicts remain errors. Preserve Java JSON insertion order. Resolve vector aliases as one parameter after merging JSON, following the updated JavaVectorIndexOptionsprecedence and optional reader metric default. Validate global declarations when their index path is used without adding generic schema-level index validation; retain existing Rust PK schema prerequisites.primary_keyprefix. Public callers use the sharedglobal_index_*/vector_index_*API. Resolve vector type, options and metric together in one serializableVectorIndexOptionsresult; remove independent configuration type lookups. Retain the complete old vector configuration (pk-vector.index.columnsplus that column'sfields.<column>.pk-vector.index.type); an orphan old field type no longer selects an implementation when Rust parses table/query options. Canonical declarations still take precedence. LogicalVectorTypestays public; query implementations are configured through ordinary declarations/options.native-index-options.md. Remove all separate vector type setters and builder/per-query hint state from Rust, Python bindings and stubs. Preserve original field JSON, canonical/legacy/DLF declarations and opaque parameters through captured readers/routes and worker tasks. PK scans select one algorithm from valid payloads (including empty markers), discard stale sources and reject mixed valid formats; configuration is used only with no valid metadata. Keep typedRawVectorSearchSplit.index_typeand persisted/index-build API metadata. Query defaults remain distinct from explicit metric constraints; PK raw and indexed reads keep Java table-metric semantics. Untyped DE FULL/DETAIL reads resolve an explicit metric from shared field JSON without selecting a backend; an explicit query metric overrides table JSON and does not parse unused invalid defaults.columns/text_fieldsaliases. Build planning respects captured historical or explicitly empty read views; option overrides preserve those views.index_type,index-type,vector.index-typeandfields.<column>.index-type; stop using an option-map bridge for raw source types. Native trainingindex.typeand typed metadata/transport fields remain supported.table/index_build. Share PK source/level planning and output validation between compaction and commit. Compact, Direct and Overwrite index deltas use one manifest merge path with layout-specific source validation; PK level-local positions remain distinct from global row IDs.global-index.num-sorted-run.compaction-trigger=5,global-index.compaction.size-ratio=1, andglobal-index.compaction.max-size-amplification-percent=200. Fully qualified keys in a column'sindex-optionsJSON override the table policy. Data-compaction settings are independent.Index declarations are unset by default.
write-only=falsemaintains declared indexes automatically; explicit PK compaction also maintains them withwrite-only=true.Tests
PK integration coverage includes all native families, physical positions, incremental/history retention, HASH/DV coexistence, independent buckets, source/index/schema conflicts, missing/tampered outputs, failure cleanup and idempotent recovery. Java empty payload fixtures exercise query-side source coverage without native file I/O.
DE LSM regressions cover independent appends through the merge threshold, small-tail selection with a retained large base, per-column overrides, shard boundaries, logical holes, overlap/removal retirement, physical source rewrites, conflict replanning and lost-publication recovery. The incremental regression fails against the former eager-rebuild implementation.
Native regressions cover scalar payload results, full-text hits/history/allow-lists and scalar FAST/FULL/DETAIL filtering, tiny and sparse IVF/PQ leaves, actual non-NULL training counts, row-ID offsets, budget-triggered expansion and all-NULL recovery. I/O assertions verify leaf builds avoid old base data and produce one final payload.
Shared selector tests and existing PK planner tests protect the unchanged PK policy. Metadata-I/O and common manifest-merge tests cover shared-buffer retention, source validation and layout-specific overlap rules.
Review regressions cover scalar type evolution/round trips and legacy schema history, stale producers, source-snapshot expiration, full-text narrowing/analyzer changes/default equivalence, native versus raw FULL/DETAIL results, vector dimension changes and idempotent failure recovery, PK field projection, hidden invalid vector values, casts before native validation, multi-file ordinal gaps at batch sizes 1/8, fully deleted source I/O, and concurrent DV removal/reduction/repacking/growth. Regressions reproduced the type-retention, full-text, vector-definition, hidden-vector and DV-restoration failures before their fixes.
Unified-option regressions cover declaration/JSON precedence, singular DLF keys, invalid legacy JSON suppressed by shared JSON, typed full-text arrays, insertion-order aliases, deterministic dimension aliases, mode-specific schema guards, per-column BTree fallback with an overridden invalid default, scoped vector query widths and refinement, and native PK/DE builds and reads. PK recovery exercises both old and shared declarations; DE FAST results agree with raw FULL/DETAIL under the same field configuration.
Resolver regressions cover metadata precedence, stale/malformed PK sources, mixed algorithms, empty markers, complete/incomplete legacy PK configuration, captured query options and shared worker transport without separate type hints.
Current complete Core: 4,814 passed, 6 ignored. Current PK/append/DE integration matrix: 160 passed. Focused follow-ups verify PK canonical/singular declarations without synthetic old field-type keys, and JSON-encoded full-text collection aliases. The raw full-map vector build regression reproduced the former strict-validator failure against the preceding SDK.
Current Python binding unit tests: 147 passed, including ordinary builders and absence of the removed setter.
Current real SDK tests: 41 passed, covering single/batch/hybrid option capture, pickle transport, metadata precedence, removed hint aliases, raw full-map vector construction, and full-text JSON collection aliases. The SDK is rebuilt from this tree and loaded with PyArrow 24. New regression cases cover untyped table/query field-JSON metrics across FULL/DETAIL and single/batch requests, plus IVF/DiskANN full-schema builds and serialized shard reconstruction. Full-text tests cover shared and flat JSON lists, including aliases, both with and without declarations; full-text construction retains complete option normalization. Both behavior failures were reproduced against the preceding SDK before their fixes.
Native Core regressions cover independent hybrid columns, canonical/singular/legacy configuration, mixed indexed/raw coverage, raw-source and serialized worker reconstruction, PK table/query metric scope, and eager invalid-input validation.
Earlier in the branch, the full
paimon --all-targets --features vortexsuite passed: 5,660 passed, 6 ignored across 86 test targets. The latest native API/configuration changes were checked with the complete core/native matrix and Python suites above.Passed
CARGO_BUILD_JOBS=2 cargo +1.98.0 clippy --locked --all-targets --workspace --features vortex -- -D warningsandcargo +1.98.0 fmt --all -- --check.API, format and documentation
CoreOptions::vector_index_options(Option<&str>, column, default_metric)returns a serializable result containing implementation, merged options and metric. A supplied metadata type wins over declarations; the default flag does not inject an unspecified query metric. Legacy PK type/metric convenience methods and independent type lookup are removed; Rust consumers use the shared index-option result. Remaining layout adapters stay crate-internal. Configuration compatibility remains independent of exposing those methods: Rust retains the complete old PK columns/type pair, while an orphan legacy field type does not select an implementation. There is no separate Native type setter or per-query hint state. Canonical/legacy/DLF declarations use ordinary options; typed persisted/source metadata remains supported.CompactResultadds optional serializedindex_entries; older results still deserialize. First publication requires re-execution when index maintenance is missing, while already published results remain recoverable. PK source metadata uses Java's existing version-1 DataOutput/writeUTF encoding. Native index formats are unchanged.Updated
docs/src/compaction.mddescribes declarations, shared maintenance boundaries, LSM policies, vector constraints, atomicity, concurrency and recovery.Legacy PK declarations/field JSON and DLF singular declarations/flat parameters remain accepted. The four removed query type hints must move to canonical declarations in ordinary table/query/route options. Before adopting shared-only PK properties, upgrade readers/writers; mixed-version deployments should retain aligned legacy declarations and field values for older clients. This change does not rewrite stored table options.