Skip to content

[test](paimon) Cover the catalog snapshot pin on the Paimon system-table source - #69569

Merged
morningman merged 1 commit into
apache:masterfrom
morningman:b2m-t14g-paimon-system-source-pin
Oct 25, 2026
Merged

morningman merged 1 commit into
apache:masterfrom
morningman:b2m-t14g-paimon-system-source-pin

Conversation

@morningman

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Related PR: #68897, #69343

Problem Summary:

In short. This PR only adds tests. Some Paimon system tables are planned on the BE. For them, the JNI scanner rebuilds the system table from the source table that the FE sends in doris.serialized-system-source. In a version-managed catalog, that payload must be pinned to the snapshot the catalog publishes. #69343 added this pin. This PR adds the two cases its tests do not cover: a scan.fallback-branch pair, and an explicit relation snapshot that must still take precedence over the pin.

Background. Six Paimon system tables are planned on the BE: $files, $file_indexes, $partitions, $manifests, $statistics and $table_indexes (PaimonScanParams#resolvesSnapshotOnBackend). For these tables the FE sends two payloads:

  • serialized_table is built by tableForBackend.
  • doris.serialized-system-source was added in [fix](paimon) Harden JNI reader options and transport #66247 so that a smaller BE can cap the manifest parallelism. The FE always sends it when the system table has a source. When it is present, PaimonJniScanner#applyBackendManifestParallelism rebuilds the system table from this payload instead of from serialized_table.

A version-managed catalog (REST) owns the committed snapshot pointer. Once the catalog loader is removed, Paimon falls back to listing the snapshot directory, and that directory can already contain a snapshot the catalog has not published. #65867 therefore pins scan.snapshot-id to the catalog's pointer (PaimonScanPlanProvider#pinCatalogSnapshot).

The problem, and what it cost. Before #69343, only serialized_table carried that pin. The side channel shipped the source unpinned, and the BE rebuilt from the side channel. So in a REST catalog these six system tables were planned on the newest snapshot in storage rather than the published one, on every branch. Inside the publication window, $partitions could list partitions of a snapshot the catalog had not published yet. The review of #68897 pointed this out for chain tables.

#69343 (the Paimon 2.1.0 upgrade) now prepares the side-channel source in the same order as tableForBackend (prepareSystemSource):

  1. Pin the catalog snapshot, branch by branch.
  2. Apply the relation's @options over the pin.
  3. Drop the catalog loader.

Its tests cover $file_indexes on a single-branch table, on the FE and through the JNI rebuild.

How this PR fixes it. Two FE unit tests in PaimonBackendBoundTableTest read the side channel out of paimon.options_json:

  • systemSourcePinsEachFallbackBranchToItsOwnCatalogSnapshot builds $partitions over a fallback pair whose two catalogs point at snapshots 2 and 1. Each branch of the transported source carries its own pointer and no catalog loader. A chain table nests the same pairs.
  • relationSnapshotOutranksTheCatalogPinOnTheSystemSource uses a catalog that points at snapshot 2 and @options('scan.snapshot-id'='1'). The transported source says 1.

Paimon 2.1.0 still has the two limitations documented on pinCatalogSnapshot:

  • $files emits its marker splits from SnapshotReader#partitions.
  • $snapshots and $buckets read without scan.snapshot-id.

So that javadoc stays as written.

Results.

prepareSystemSource PaimonBackendBoundTableTest
as on master (pin, then @options) 38 / 38 pass
without the pin the new fallback case and the existing $file_indexes case fail
pin applied after the relation options the new relation-snapshot case fails (expected: <1> but was: <2>)

All 847 tests of fe-connector-paimon pass, with 1 skipped as before, and checkstyle passes. No regression suite is added: it would need a version-managed (REST) Paimon catalog whose pointer lags the snapshot directory, and the docker fixtures do not provide one.

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

…ble source

### What problem does this PR solve?

Issue Number: None

Related PR: apache#68897, apache#69343

Problem Summary: For the Paimon system tables that plan on the BE
($files, $file_indexes, $partitions, $manifests, $statistics,
$table_indexes) the FE also sends the system table's source table in
doris.serialized-system-source, and the JNI scanner rebuilds the system
table from that payload instead of serialized_table. Until apache#69343 only
serialized_table carried the catalog snapshot pin (scan.snapshot-id taken
from a version-managed catalog's pointer, apache#65867), so in a REST catalog
these system tables were planned on the newest snapshot in storage rather
than the one the catalog publishes, on every branch, since the side channel
was added (apache#66247); the review of apache#68897 pointed this out for chain tables.
apache#69343 (the Paimon 2.1.0 upgrade) now prepares that source the way
tableForBackend prepares serialized_table: pin the catalog snapshot branch
by branch, apply the relation's @options over it, then drop the catalog
loader. Its tests cover $file_indexes on a single-branch table.

This adds the two cases that are not covered yet:

- a scan.fallback-branch pair: each branch of the transported source
  carries its own catalog pointer and no catalog loader (a chain table
  nests the same pairs);
- an explicit relation snapshot still wins over the catalog pin on the
  transported source.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - PaimonBackendBoundTableTest: 2 new cases, 38 in all
    - Without the pin in prepareSystemSource the fallback case fails, and pinning after the relation options makes the snapshot case fail
- Behavior changed: No
- Does this need documentation: No

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@morningman

Copy link
Copy Markdown
Contributor Author

run buildall

@morningman

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed PR #69569 at head 8109fea964893f5f7d1f04d322b7109ea3025c17 using static analysis. No new actionable findings and no existing blocking inline comments were identified. No additional user focus was supplied.

The tests cover the intended FE transport boundary: each fallback branch retains its own catalog snapshot and loses its catalog loader in doris.serialized-system-source, while an explicit relation snapshot overrides the catalog pin. The helper decodes the same source payload that JNI uses to rebuild the system table.

Code-review checkpoint conclusions:

  • Goal and proof: the new payload assertions distinguish independent branch pins (2/1) and relation precedence (1 over catalog 2). Test execution was outside this review's scope.
  • Scope and reuse: the change is confined to two JUnit tests and a helper that reuses the existing provider, fixture, and deserializer.
  • Concurrency and locks: no new concurrency or locking; each test uses its own temporary warehouse and local catalog instances.
  • Lifecycle and initialization: existing commit helpers close writers and committers; no new static initialization, shared mutable fixture, or lifetime dependency is introduced.
  • Configuration: no production configuration is added or changed.
  • Compatibility: no production API, function symbol, storage format, or upgrade behavior changes.
  • Thrift/protobuf: no definitions change.
  • Parallel paths: traced both serialized-table and system-source construction, branch-by-branch pinning, loader removal, and JNI reconstruction; existing file-index and chain-source tests cover adjacent reconstruction paths.
  • Conditions and errors: missing payloads, wrong pins, lost fallback wrappers, and retained loaders fail assertions or deserialization; the catalog call counter supplements the payload assertion.
  • Test coverage: both requested transport cases are covered. Existing neighboring tests address filesystem catalogs, other system tables, incremental options, and failure paths. These two additions do not execute a complete JNI fallback query.
  • Expected results: only inline assertions are added; no generated regression results are modified. Expected snapshot values match the fixture pointers and relation options.
  • Observability: no runtime path changes requiring new logging or metrics.
  • Transactions and persistence: production transaction, EditLog, replay, and failover behavior is unchanged; snapshot writes are confined to test fixtures.
  • Data writes and atomicity: test data uses the existing scoped batch-write/commit helper; no production write path changes.
  • FE/BE propagation: no new transmitted variable; the helper reads the existing options JSON key consumed by the scanner.
  • Performance: two small local fixtures and one additional payload decode per test; no production hot path changes.
  • Other issues and core invariants: no substantiated regression in snapshot transport, error propagation, fixture isolation, memory ownership, or production data/version/delete-bitmap behavior was found.

Validation limits: no builds, unit tests, regression tests, Checkstyle execution, or mutation experiments were run. Review coverage includes every changed hunk and the relevant producer/consumer paths; there are no unresolved candidates or unreviewed changed files. Review converged in one round.

Review converged after 1 round(s).

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28698 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 8109fea964893f5f7d1f04d322b7109ea3025c17, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17606	5162	5077	5077
q2	2105	324	261	261
q3	10234	1404	816	816
q4	4684	467	338	338
q5	7434	796	523	523
q6	184	182	149	149
q7	741	796	609	609
q8	9245	1328	1046	1046
q9	5530	4204	4167	4167
q10	6823	1296	1026	1026
q11	428	243	224	224
q12	633	402	285	285
q13	18078	3562	3006	3006
q14	272	282	251	251
q15	q16	731	722	656	656
q17	1202	740	578	578
q18	7026	6197	6125	6125
q19	1118	947	619	619
q20	387	337	225	225
q21	5494	2469	2447	2447
q22	385	339	270	270
Total cold run time: 100340 ms
Total hot run time: 28698 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5930	5863	6069	5863
q2	694	569	588	569
q3	5669	5771	5202	5202
q4	2061	2153	1648	1648
q5	5787	5752	5668	5668
q6	239	183	141	141
q7	2244	1969	1762	1762
q8	3052	2672	2587	2587
q9	8141	7784	7823	7784
q10	3639	3558	3142	3142
q11	576	409	385	385
q12	670	661	505	505
q13	3239	3540	3031	3031
q14	291	283	267	267
q15	q16	677	673	599	599
q17	7711	7071	6931	6931
q18	12974	12181	12884	12181
q19	882	778	783	778
q20	2146	2129	1923	1923
q21	5725	4595	4725	4595
q22	505	446	389	389
Total cold run time: 72852 ms
Total hot run time: 65950 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 150217 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 8109fea964893f5f7d1f04d322b7109ea3025c17, data reload: false

query5	4308	598	454	454
query6	458	211	185	185
query7	4798	444	228	228
query8	314	169	154	154
query9	8797	3105	3108	3105
query10	491	308	276	276
query11	5920	3847	3579	3579
query12	141	90	87	87
query13	1259	429	344	344
query14	6158	3945	3676	3676
query14_1	3445	3374	3456	3374
query15	208	204	180	180
query16	933	412	404	404
query17	827	623	516	516
query18	2398	407	295	295
query19	189	160	126	126
query20	82	81	80	80
query21	204	122	104	104
query22	12936	12982	12753	12753
query23	13400	12890	12387	12387
query23_1	12537	12489	12476	12476
query24	7355	805	457	457
query24_1	463	467	457	457
query25	514	393	336	336
query26	1259	258	135	135
query27	2771	434	275	275
query28	4611	1957	1979	1957
query29	1554	581	429	429
query30	300	217	181	181
query31	1008	926	801	801
query32	145	85	89	85
query33	520	291	234	234
query34	899	834	481	481
query35	731	731	637	637
query36	814	800	732	732
query37	129	93	82	82
query38	1767	1753	1669	1669
query39	796	790	740	740
query39_1	738	718	740	718
query40	210	109	97	97
query41	64	61	61	61
query42	93	83	82	82
query43	347	353	313	313
query44	1292	678	676	676
query45	175	178	164	164
query46	821	969	563	563
query47	3000	2797	2650	2650
query48	298	307	228	228
query49	569	396	292	292
query50	686	264	208	208
query51	10338	10297	10268	10268
query52	78	86	69	69
query53	184	207	151	151
query54	229	194	192	192
query55	75	68	65	65
query56	231	232	202	202
query57	1625	1598	1580	1580
query58	286	278	278	278
query59	2102	2180	1926	1926
query60	308	252	238	238
query61	168	168	169	168
query62	385	350	286	286
query63	193	165	168	165
query64	2875	1051	875	875
query65	3319	3268	3269	3268
query66	1798	439	317	317
query67	20223	20170	19834	19834
query68	2986	996	617	617
query69	392	306	260	260
query70	814	783	775	775
query71	320	239	210	210
query72	3061	2624	2281	2281
query73	519	518	291	291
query74	4608	4520	4355	4355
query75	2342	2287	1936	1936
query76	2327	1012	592	592
query77	339	368	269	269
query78	9842	9655	9183	9183
query79	1664	846	524	524
query80	1237	408	349	349
query81	588	319	270	270
query82	565	128	100	100
query83	299	193	179	179
query84	311	165	108	108
query85	845	417	366	366
query86	398	236	230	230
query87	2009	1940	1819	1819
query88	3731	2686	2653	2653
query89	334	289	241	241
query90	1867	170	177	170
query91	161	148	125	125
query92	98	89	88	88
query93	1127	1014	571	571
query94	641	321	267	267
query95	580	390	297	297
query96	662	492	236	236
query97	2464	2408	2318	2318
query98	158	158	145	145
query99	774	757	647	647
Total cold run time: 236009 ms
Total hot run time: 150217 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.26 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 8109fea964893f5f7d1f04d322b7109ea3025c17, data reload: false

query1	0.01	0.01	0.00
query2	0.09	0.05	0.05
query3	0.26	0.09	0.09
query4	1.61	0.10	0.11
query5	0.23	0.24	0.23
query6	1.16	0.68	0.67
query7	0.04	0.01	0.00
query8	0.06	0.04	0.04
query9	0.41	0.36	0.35
query10	0.58	0.56	0.61
query11	0.19	0.15	0.14
query12	0.18	0.16	0.15
query13	0.49	0.50	0.49
query14	1.03	1.00	1.01
query15	0.63	0.62	0.60
query16	0.35	0.35	0.34
query17	1.16	1.13	1.11
query18	0.21	0.20	0.19
query19	2.11	1.94	2.00
query20	0.02	0.02	0.01
query21	15.50	0.21	0.14
query22	4.67	0.05	0.05
query23	16.27	0.34	0.12
query24	3.06	0.47	0.41
query25	0.13	0.04	0.06
query26	1.16	0.21	0.16
query27	0.04	0.03	0.02
query28	3.14	0.80	0.38
query29	12.57	4.09	3.23
query30	0.27	0.13	0.10
query31	2.77	0.54	0.32
query32	3.22	0.60	0.51
query33	3.23	3.22	3.23
query34	15.34	4.02	3.40
query35	3.29	3.33	3.34
query36	0.55	0.42	0.41
query37	0.09	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.17	0.15	0.14
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.03
Total cold run time: 96.55 s
Total hot run time: 24.26 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 0.00% (0/14) 🎉
Increment coverage report
Complete coverage report

@morningman
morningman merged commit 76fb880 into apache:master Oct 25, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants