Public report — risingwave, published 29 Sep 2026.
Concrete security findings (which rule fired, in which file, on which line; CVE IDs, secret matches,
dependency versions) are REDACTED in this version; ask the repo owner for the full report.
Public
Codebase surveyMeasured under the Code Assurance Index · rubric rubric-2026.09.17 (frozen) · verify this surveyFiledcd_e6f35d56badc46de93f8127bd5111fb7
Filed 29 September 2026, 05:54 UTC
Public
Very large · 773,399 LoC · 81 projects · rebuild ~7.4 person-years · weakest lens: Readiness (59%)
Findings by grade
278 critical2936 serious47 minor41 could not be resolved — could be critical — see Limitations
This survey was produced by
Watchdog
Producer
Canine Development
Analyzer
Watchdog engine 1.0.0
Measured
29 September 2026, 04:58 UTC
A measurement, not a certificate. The Code Assurance Index does not certify,
approve or guarantee this codebase; it records a reproducible number and the evidence it was computed from. The
standard is authored by Canine Development, who also build Watchdog — its only implementation today. That is said
here so the number is checked rather than believed.
Grounded in facts. Every number here is computed, not narrated — reproducible, tool-backed, and traceable to a line of code. How to trust this ▸
3202findings with an exact file:lineof 3261 — the remainder are repo-wide signals (a dimension-level measurement, not a single line); open any file:line and verify
67/135dimensions across the health lenses773399 LoC · 81 projects — wide & deep
The system holds an adequate standing with a health score of 62%, reflecting a large, complex asset that is functional but carries significant operational risk. With nearly 774,000 lines of production code, the platform represents a substantial investment, estimated at roughly €1.1 million and 7.4 person-years to rebuild. This scale means that even minor inefficiencies compound into major costs, making the current state a workable but fragile foundation for future growth.
The most critical vulnerability lies in security exposure, specifically regarding leaked secrets in configuration files. This is not merely a technical oversight but a direct threat to business continuity and compliance. Resolving these four findings is the highest-leverage action available, costing only a few engineer-days to fix while preventing potential annual losses equivalent to hundreds of engineering days. Ignoring this risk creates a liability that pays a heavy tax in potential breach response and reputational damage.
A second major theme is operational fragility, driven by low production readiness scores. The system lacks the robustness required for its size, meaning changes ripple unpredictably and outages are more likely. This weakness concentrates risk across the entire platform, as the team cannot reliably predict how modifications will behave in production. The lack of measured test coverage in key areas further obscures the true state of stability, leaving the business flying blind regarding regression risks.
Despite these risks, the codebase demonstrates genuine strength in architectural consistency and domain modeling, with high scores in event sourcing and performance. The code is well-structured, which provides a solid base for improvement. However, a velocity tax exists: the average code quality forces teams to spend 4–9% more effort on every change due to complexity and duplication. This drag slows delivery and increases costs over time.
Focus first on securing the leaked credentials, as this action pays for itself within months. Once secured, prioritize improving production readiness to stabilize the platform. The current picture is partial, as test coverage was not measured, so assume hidden risks remain in untested areas.
How the score is built — each lens's share of the headlineWidth is the lens's weight in the worst-heaviest fold (the weakest area pulls hardest); colour is that lens's own band. A lens fixes the score in proportion to its width.
237 finding(s) are new versus the previous scan (2026-09-12) — surfaced by this scheduled scan itself, no pull request required. Showing the first 100; the full set is in the report.
D4 · Edited copy of a member (32 corresponding lines) REDACTED
D4 · Members sharing a duplicated core (4 members, 50+ identical tokens) e2e_test/s3/file_sink.py
D4 · Members sharing a duplicated core (4 members, 50+ identical tokens) e2e_test/webhook/websocket_sender.py
D4 · Members sharing a duplicated core (4 members, 50+ identical tokens) integration_tests/iceberg-cdc/python/script/init.py
A full-fidelity diff against the previous run's complete recorded findings — line-move tolerant: a finding that only shifted line counts as unchanged, only genuinely new titles/files surface here.
Rebuild cost & value ~ Modeled — €360,000–€1,800,000
0.8× (at 62% quality) — the last 20% of quality is most of the work
Size & shape
Very large · effort split not classified (source measured from disk; the effort-tier breakdown is a C#-only syntax walk)
This codebase represents roughly ~7.4 person-years of build effort (about ~€1,100,000 to rebuild). Its weakest lens is Readiness at 59% — the part of that asset most exposed by the findings below.
How we model this: boilerplate at a scaffolding rate + logic × domain Standard (×1.2) — domain model × a 0.8× quality factor, at €60–95/h; indicative, ±~30% · size measured directly from source · effort from total production LoC as straight-line logic (the tier split is a C#-only syntax walk), a conservative lower bound. Indicative only — most sensitive to the hourly rate and the domain tier (both tunable in config).
Top priorities
The highest-leverage moves; the full ranked list is in the Roadmap below.
1
Resolve the 4 Leaked secret finding(s) in REDACTED Scanning — start with REDACTED, REDACTED, REDACTED.
The top-ranked fix costs roughly 1–3 engineer-days once. Not doing it costs about 63.1–378.8 engineer-days every year, paid as drag on the ~606,914 lines this team changes annually — a bill that arrives whether or not anyone books it. On those figures the fix breaks even in roughly 1–2 months and is free after that. Method, stated so this is not read as a quotation: debt from the ranked task's effort band; interest = annual changed lines (measured, annualised from the 90-day window) ÷ an ASSUMED 150–400 lines per engineer-day × the 4–9% drag implied by the code-quality signals; breaking point = debt ÷ annual interest. A modelled planning range built from measured inputs and one named assumption — not a quotation, a valuation, or a certified figure.
Evidence: D15 churn: 149,650 line(s) changed over a 90-day window ⇒ ~606,914/year · D1/D2/D4 code quality: averaging 6.3/10 ⇒ a 4–9% drag on each change · top-ranked remediation: Low effort ⇒ about 1–3 engineer-day(s)
→ Do the top-ranked fix now if this code will still be yours in 2 months.
Value concentrated against a weak lens · Medium · Value at risk
This is a Very large asset (~7.4 person-years to rebuild), and its weakest lens is Readiness at 59%. The operational and business risk on an asset this size concentrates there — that's where remediation buys the most protection.
→ Direct remediation budget at Readiness first — highest risk-reduction per euro on an asset this size.
Highest-leverage move · Medium · Leverage
Of everything flagged, the best return on effort is: Resolve the 4 Leaked secret finding(s) in REDACTED Scanning — start with REDACTED, REDACTED, REDACTED. The rest can wait behind it.
Evidence: priority ranking: top of 5 ranked by impact/effort
→ Resolve the 4 Leaked secret finding(s) in REDACTED Scanning — start with REDACTED, REDACTED, REDACTED.
A velocity tax on every change · Medium · Economics
The code-quality signals (complexity, duplication, cohesion) average 6.3/10, which acts as a tax on every change in the weaker areas: modifications there plausibly cost on the order of 4–9% more than in clean code, and the tax compounds as the codebase grows. (A modelled estimate, not a measured fact.)
Evidence: D1/D2/D4 code quality: averaging 6.3/10 across the code-quality signals actually measured
→ Pay it down where churn is highest — the hotspots — not everywhere; that's where the tax is actually paid.
Architecture — module dependency graph
Project dependencies, layered top-to-bottom; arrows show direction. Any dashed red edge points upward or sideways — a layering smell or cycle. A clean layered graph has none.
Architecture — module dependency matrix
Rows and columns are the same modules, ordered so that a module only depends on ones above it. A cell means the row depends on the column, and its number is how many type pairs create that dependency. Read one thing: is anything above the diagonal? A mark there is a dependency cycle. (A cycle is all this shows — an unusual but cycle-free dependency sits below the diagonal like any other.)
2502 modules, 8673 dependencies. 15 dependency cycles across 471 modules, marked above the diagonal.
Showing the 40 most-connected modules; 2462 more are not drawn.
Module dependency matrix. The row depends on the column; the number is how many type pairs create the dependency. A cell above the diagonal is part of a dependency cycle.
risingwave_common.bitmap uses risingwave_common_estimate_size. Changing risingwave_common_estimate_size can break risingwave_common.bitmap, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
7→3 risingwave_common.bitmap depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_common.bitmap → type in risingwave_expr_impl.scalar.format) reference.
risingwave_common.bitmap uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.bitmap, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
8→1 risingwave_common.row.owned_row depends on risingwave_common_estimate_size✕
Type pairs
1 distinct (type in risingwave_common.row.owned_row → type in risingwave_common_estimate_size) reference.
risingwave_common.row.owned_row uses risingwave_common_estimate_size. Changing risingwave_common_estimate_size can break risingwave_common.row.owned_row, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
9→22 risingwave_common.util.epoch depends on risingwave_common.typescycle✕
Type pairs
1 distinct (type in risingwave_common.util.epoch → type in risingwave_common.types) reference.
risingwave_frontend.handler.explain_analyze_stream_job.graph uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_frontend.handler.explain_analyze_stream_job.graph, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
11→34 risingwave_frontend.optimizer.plan_node.expr_rewritable depends on risingwave_frontend.optimizer.plan_nodecycle✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node.expr_rewritable → type in risingwave_frontend.optimizer.plan_node) reference.
risingwave_frontend.optimizer.plan_node.expr_rewritable uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_frontend.optimizer.plan_node.expr_rewritable, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
12→5 risingwave_storage.hummock.iterator.merge_inner depends on risingwave_meta.manager.notification✕
Type pairs
1 distinct (type in risingwave_storage.hummock.iterator.merge_inner → type in risingwave_meta.manager.notification) reference.
risingwave_storage.hummock.iterator.merge_inner uses risingwave_meta.manager.notification. Changing risingwave_meta.manager.notification can break risingwave_storage.hummock.iterator.merge_inner, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
13→9 risingwave_frontend.catalog.table_catalog depends on risingwave_common.util.epoch✕
Type pairs
1 distinct (type in risingwave_frontend.catalog.table_catalog → type in risingwave_common.util.epoch) reference.
risingwave_frontend.catalog.table_catalog uses risingwave_common.util.epoch. Changing risingwave_common.util.epoch can break risingwave_frontend.catalog.table_catalog, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
13→15 risingwave_frontend.catalog.table_catalog depends on risingwave_frontend.exprcycle✕
Type pairs
1 distinct (type in risingwave_frontend.catalog.table_catalog → type in risingwave_frontend.expr) reference.
risingwave_frontend.catalog.table_catalog uses risingwave_frontend.expr. Changing risingwave_frontend.expr can break risingwave_frontend.catalog.table_catalog, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
13→24 risingwave_frontend.catalog.table_catalog depends on risingwave_common.catalog.columncycle✕
Type pairs
3 distinct (type in risingwave_frontend.catalog.table_catalog → type in risingwave_common.catalog.column) references.
risingwave_frontend.catalog.table_catalog uses risingwave_common.catalog.column. Changing risingwave_common.catalog.column can break risingwave_frontend.catalog.table_catalog, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
13→26 risingwave_frontend.catalog.table_catalog depends on risingwave_common.catalog.schemacycle✕
Type pairs
1 distinct (type in risingwave_frontend.catalog.table_catalog → type in risingwave_common.catalog.schema) reference.
risingwave_frontend.catalog.table_catalog uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_frontend.catalog.table_catalog, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
14→3 risingwave_frontend.utils.condition depends on risingwave_expr_impl.scalar.format✕
Type pairs
2 distinct (type in risingwave_frontend.utils.condition → type in risingwave_expr_impl.scalar.format) references.
risingwave_frontend.utils.condition uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_frontend.utils.condition, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
14→13 risingwave_frontend.utils.condition depends on risingwave_frontend.catalog.table_catalog✕
Type pairs
1 distinct (type in risingwave_frontend.utils.condition → type in risingwave_frontend.catalog.table_catalog) reference.
risingwave_frontend.utils.condition uses risingwave_frontend.catalog.table_catalog. Changing risingwave_frontend.catalog.table_catalog can break risingwave_frontend.utils.condition, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
14→15 risingwave_frontend.utils.condition depends on risingwave_frontend.exprcycle✕
Type pairs
1 distinct (type in risingwave_frontend.utils.condition → type in risingwave_frontend.expr) reference.
risingwave_frontend.utils.condition uses risingwave_frontend.expr. Changing risingwave_frontend.expr can break risingwave_frontend.utils.condition, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
14→22 risingwave_frontend.utils.condition depends on risingwave_common.typescycle✕
Type pairs
1 distinct (type in risingwave_frontend.utils.condition → type in risingwave_common.types) reference.
risingwave_frontend.utils.condition uses risingwave_common.types. Changing risingwave_common.types can break risingwave_frontend.utils.condition, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
14→26 risingwave_frontend.utils.condition depends on risingwave_common.catalog.schemacycle✕
Type pairs
1 distinct (type in risingwave_frontend.utils.condition → type in risingwave_common.catalog.schema) reference.
risingwave_frontend.utils.condition uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_frontend.utils.condition, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
15→3 risingwave_frontend.expr depends on risingwave_expr_impl.scalar.format✕
Type pairs
2 distinct (type in risingwave_frontend.expr → type in risingwave_expr_impl.scalar.format) references.
risingwave_frontend.expr uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_frontend.expr, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
15→8 risingwave_frontend.expr depends on risingwave_common.row.owned_row✕
Type pairs
1 distinct (type in risingwave_frontend.expr → type in risingwave_common.row.owned_row) reference.
risingwave_frontend.expr uses risingwave_common.row.owned_row. Changing risingwave_common.row.owned_row can break risingwave_frontend.expr, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
15→14 risingwave_frontend.expr depends on risingwave_frontend.utils.condition✕
Type pairs
1 distinct (type in risingwave_frontend.expr → type in risingwave_frontend.utils.condition) reference.
risingwave_frontend.expr uses risingwave_frontend.utils.condition. Changing risingwave_frontend.utils.condition can break risingwave_frontend.expr, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
15→21 risingwave_frontend.expr depends on risingwave_common.types.jsonbcycle✕
Type pairs
1 distinct (type in risingwave_frontend.expr → type in risingwave_common.types.jsonb) reference.
risingwave_frontend.expr uses risingwave_common.types.jsonb. Changing risingwave_common.types.jsonb can break risingwave_frontend.expr, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
15→22 risingwave_frontend.expr depends on risingwave_common.typescycle✕
Type pairs
2 distinct (type in risingwave_frontend.expr → type in risingwave_common.types) references.
risingwave_frontend.expr uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_frontend.expr, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
16→3 risingwave_common.util.column_index_mapping depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_common.util.column_index_mapping → type in risingwave_expr_impl.scalar.format) reference.
risingwave_common.util.column_index_mapping uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.util.column_index_mapping, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
16→15 risingwave_common.util.column_index_mapping depends on risingwave_frontend.expr✕
Type pairs
1 distinct (type in risingwave_common.util.column_index_mapping → type in risingwave_frontend.expr) reference.
risingwave_common.util.column_index_mapping uses risingwave_frontend.expr. Changing risingwave_frontend.expr can break risingwave_common.util.column_index_mapping, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
17→3 risingwave_sqlparser.ast depends on risingwave_expr_impl.scalar.format✕
Type pairs
60 distinct (type in risingwave_sqlparser.ast → type in risingwave_expr_impl.scalar.format) references. Showing 25 of them; the rest are in namespace-graph.json in this report's bundle.
risingwave_sqlparser.ast uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_sqlparser.ast, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
17→15 risingwave_sqlparser.ast depends on risingwave_frontend.expr✕
Type pairs
5 distinct (type in risingwave_sqlparser.ast → type in risingwave_frontend.expr) references.
risingwave_sqlparser.ast uses risingwave_sqlparser.ast.value. Changing risingwave_sqlparser.ast.value can break risingwave_sqlparser.ast, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
17→22 risingwave_sqlparser.ast depends on risingwave_common.typescycle✕
Type pairs
2 distinct (type in risingwave_sqlparser.ast → type in risingwave_common.types) references.
risingwave_frontend.optimizer.plan_node.convert uses risingwave_common.util.column_index_mapping. Changing risingwave_common.util.column_index_mapping can break risingwave_frontend.optimizer.plan_node.convert, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
19→16 risingwave_frontend.optimizer.plan_node.plan_tree_node depends on risingwave_common.util.column_index_mapping✕
Type pairs
2 distinct (type in risingwave_frontend.optimizer.plan_node.plan_tree_node → type in risingwave_common.util.column_index_mapping) references.
risingwave_frontend.optimizer.plan_node.plan_tree_node uses risingwave_common.util.column_index_mapping. Changing risingwave_common.util.column_index_mapping can break risingwave_frontend.optimizer.plan_node.plan_tree_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
19→34 risingwave_frontend.optimizer.plan_node.plan_tree_node depends on risingwave_frontend.optimizer.plan_nodecycle✕
Type pairs
3 distinct (type in risingwave_frontend.optimizer.plan_node.plan_tree_node → type in risingwave_frontend.optimizer.plan_node) references.
risingwave_frontend.optimizer.plan_node.plan_tree_node uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_frontend.optimizer.plan_node.plan_tree_node, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
20→1 risingwave_sqlparser.ast.value depends on risingwave_common_estimate_size✕
Type pairs
1 distinct (type in risingwave_sqlparser.ast.value → type in risingwave_common_estimate_size) reference.
risingwave_sqlparser.ast.value uses risingwave_common_estimate_size. Changing risingwave_common_estimate_size can break risingwave_sqlparser.ast.value, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
20→3 risingwave_sqlparser.ast.value depends on risingwave_expr_impl.scalar.format✕
Type pairs
9 distinct (type in risingwave_sqlparser.ast.value → type in risingwave_expr_impl.scalar.format) references.
risingwave_sqlparser.ast.value uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_sqlparser.ast.value, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
20→17 risingwave_sqlparser.ast.value depends on risingwave_sqlparser.ast✕
Type pairs
2 distinct (type in risingwave_sqlparser.ast.value → type in risingwave_sqlparser.ast) references.
risingwave_sqlparser.ast.value uses risingwave_sqlparser.ast. Changing risingwave_sqlparser.ast can break risingwave_sqlparser.ast.value, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
21→1 risingwave_common.types.jsonb depends on risingwave_common_estimate_size✕
Type pairs
1 distinct (type in risingwave_common.types.jsonb → type in risingwave_common_estimate_size) reference.
risingwave_common.types.jsonb uses risingwave_common_estimate_size. Changing risingwave_common_estimate_size can break risingwave_common.types.jsonb, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
21→3 risingwave_common.types.jsonb depends on risingwave_expr_impl.scalar.format✕
Type pairs
3 distinct (type in risingwave_common.types.jsonb → type in risingwave_expr_impl.scalar.format) references.
risingwave_common.types.jsonb uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.types.jsonb, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
21→20 risingwave_common.types.jsonb depends on risingwave_sqlparser.ast.value✕
Type pairs
1 distinct (type in risingwave_common.types.jsonb → type in risingwave_sqlparser.ast.value) reference.
risingwave_common.types.jsonb uses risingwave_sqlparser.ast.value. Changing risingwave_sqlparser.ast.value can break risingwave_common.types.jsonb, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
21→22 risingwave_common.types.jsonb depends on risingwave_common.typescycle✕
Type pairs
6 distinct (type in risingwave_common.types.jsonb → type in risingwave_common.types) references.
risingwave_common.types uses risingwave_common_estimate_size. Changing risingwave_common_estimate_size can break risingwave_common.types, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
22→3 risingwave_common.types depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_common.types → type in risingwave_expr_impl.scalar.format) reference.
risingwave_common.types uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.types, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
22→21 risingwave_common.types depends on risingwave_common.types.jsonb✕
Type pairs
3 distinct (type in risingwave_common.types → type in risingwave_common.types.jsonb) references.
risingwave_common.array.data_chunk uses risingwave_common_estimate_size. Changing risingwave_common_estimate_size can break risingwave_common.array.data_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
23→3 risingwave_common.array.data_chunk depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_common.array.data_chunk → type in risingwave_expr_impl.scalar.format) reference.
risingwave_common.array.data_chunk uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.array.data_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
23→7 risingwave_common.array.data_chunk depends on risingwave_common.bitmap✕
Type pairs
1 distinct (type in risingwave_common.array.data_chunk → type in risingwave_common.bitmap) reference.
risingwave_common.array.data_chunk uses risingwave_common.bitmap. Changing risingwave_common.bitmap can break risingwave_common.array.data_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
23→22 risingwave_common.array.data_chunk depends on risingwave_common.types✕
Type pairs
1 distinct (type in risingwave_common.array.data_chunk → type in risingwave_common.types) reference.
risingwave_common.array.data_chunk uses risingwave_common.types. Changing risingwave_common.types can break risingwave_common.array.data_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
24→3 risingwave_common.catalog.column depends on risingwave_expr_impl.scalar.format✕
Type pairs
2 distinct (type in risingwave_common.catalog.column → type in risingwave_expr_impl.scalar.format) references.
risingwave_common.catalog.column uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.catalog.column, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
24→5 risingwave_common.catalog.column depends on risingwave_meta.manager.notification✕
Type pairs
1 distinct (type in risingwave_common.catalog.column → type in risingwave_meta.manager.notification) reference.
risingwave_common.catalog.column uses risingwave_meta.manager.notification. Changing risingwave_meta.manager.notification can break risingwave_common.catalog.column, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
24→22 risingwave_common.catalog.column depends on risingwave_common.types✕
Type pairs
2 distinct (type in risingwave_common.catalog.column → type in risingwave_common.types) references.
risingwave_common.catalog.column uses risingwave_common.types. Changing risingwave_common.types can break risingwave_common.catalog.column, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
24→26 risingwave_common.catalog.column depends on risingwave_common.catalog.schemacycle✕
Type pairs
3 distinct (type in risingwave_common.catalog.column → type in risingwave_common.catalog.schema) references.
risingwave_common.catalog.column uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_common.catalog.column, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
25→2 risingwave_frontend.session depends on risingwave_dml.txn_channel✕
Type pairs
1 distinct (type in risingwave_frontend.session → type in risingwave_dml.txn_channel) reference.
risingwave_frontend.session uses risingwave_dml.txn_channel. Changing risingwave_dml.txn_channel can break risingwave_frontend.session, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
25→3 risingwave_frontend.session depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_frontend.session → type in risingwave_expr_impl.scalar.format) reference.
risingwave_frontend.session uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_frontend.session, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
25→13 risingwave_frontend.session depends on risingwave_frontend.catalog.table_catalog✕
Type pairs
2 distinct (type in risingwave_frontend.session → type in risingwave_frontend.catalog.table_catalog) references.
risingwave_frontend.session uses risingwave_frontend.catalog.table_catalog. Changing risingwave_frontend.catalog.table_catalog can break risingwave_frontend.session, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
25→17 risingwave_frontend.session depends on risingwave_sqlparser.ast✕
Type pairs
3 distinct (type in risingwave_frontend.session → type in risingwave_sqlparser.ast) references.
risingwave_common.catalog.schema uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.catalog.schema, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
26→22 risingwave_common.catalog.schema depends on risingwave_common.types✕
Type pairs
3 distinct (type in risingwave_common.catalog.schema → type in risingwave_common.types) references.
risingwave_common.catalog.schema uses risingwave_common.types. Changing risingwave_common.types can break risingwave_common.catalog.schema, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
26→24 risingwave_common.catalog.schema depends on risingwave_common.catalog.column✕
Type pairs
1 distinct (type in risingwave_common.catalog.schema → type in risingwave_common.catalog.column) reference.
risingwave_common.catalog.schema uses risingwave_common.catalog.column. Changing risingwave_common.catalog.column can break risingwave_common.catalog.schema, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
27→8 risingwave_expr.expr depends on risingwave_common.row.owned_row✕
Type pairs
5 distinct (type in risingwave_expr.expr → type in risingwave_common.row.owned_row) references.
risingwave_expr.expr uses risingwave_common.array.data_chunk. Changing risingwave_common.array.data_chunk can break risingwave_expr.expr, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
28→24 risingwave_frontend.catalog.system_catalog depends on risingwave_common.catalog.column✕
Type pairs
1 distinct (type in risingwave_frontend.catalog.system_catalog → type in risingwave_common.catalog.column) reference.
risingwave_frontend.catalog.system_catalog uses risingwave_common.catalog.column. Changing risingwave_common.catalog.column can break risingwave_frontend.catalog.system_catalog, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
28→25 risingwave_frontend.catalog.system_catalog depends on risingwave_frontend.session✕
Type pairs
1 distinct (type in risingwave_frontend.catalog.system_catalog → type in risingwave_frontend.session) reference.
risingwave_frontend.catalog.system_catalog uses risingwave_frontend.session. Changing risingwave_frontend.session can break risingwave_frontend.catalog.system_catalog, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
29→26 risingwave_batch.executor depends on risingwave_common.catalog.schema✕
Type pairs
2 distinct (type in risingwave_batch.executor → type in risingwave_common.catalog.schema) references.
risingwave_batch.executor uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_batch.executor, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
30→1 risingwave_common.array.stream_chunk depends on risingwave_common_estimate_size✕
Type pairs
1 distinct (type in risingwave_common.array.stream_chunk → type in risingwave_common_estimate_size) reference.
risingwave_common.array.stream_chunk uses risingwave_common_estimate_size. Changing risingwave_common_estimate_size can break risingwave_common.array.stream_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
30→3 risingwave_common.array.stream_chunk depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_common.array.stream_chunk → type in risingwave_expr_impl.scalar.format) reference.
risingwave_common.array.stream_chunk uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_common.array.stream_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
30→5 risingwave_common.array.stream_chunk depends on risingwave_meta.manager.notification✕
Type pairs
1 distinct (type in risingwave_common.array.stream_chunk → type in risingwave_meta.manager.notification) reference.
risingwave_common.array.stream_chunk uses risingwave_meta.manager.notification. Changing risingwave_meta.manager.notification can break risingwave_common.array.stream_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
30→7 risingwave_common.array.stream_chunk depends on risingwave_common.bitmap✕
Type pairs
2 distinct (type in risingwave_common.array.stream_chunk → type in risingwave_common.bitmap) references.
risingwave_common.array.stream_chunk uses risingwave_common.bitmap. Changing risingwave_common.bitmap can break risingwave_common.array.stream_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
30→23 risingwave_common.array.stream_chunk depends on risingwave_common.array.data_chunk✕
Type pairs
1 distinct (type in risingwave_common.array.stream_chunk → type in risingwave_common.array.data_chunk) reference.
risingwave_common.array.stream_chunk uses risingwave_common.array.data_chunk. Changing risingwave_common.array.data_chunk can break risingwave_common.array.stream_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
30→26 risingwave_common.array.stream_chunk depends on risingwave_common.catalog.schema✕
Type pairs
1 distinct (type in risingwave_common.array.stream_chunk → type in risingwave_common.catalog.schema) reference.
risingwave_common.array.stream_chunk uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_common.array.stream_chunk, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
31→7 risingwave_connector.sink depends on risingwave_common.bitmap✕
Type pairs
1 distinct (type in risingwave_connector.sink → type in risingwave_common.bitmap) reference.
risingwave_connector.sink uses risingwave_common.catalog.column. Changing risingwave_common.catalog.column can break risingwave_connector.sink, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
31→26 risingwave_connector.sink depends on risingwave_common.catalog.schema✕
Type pairs
1 distinct (type in risingwave_connector.sink → type in risingwave_common.catalog.schema) reference.
risingwave_connector.sink uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_connector.sink, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
32→26 risingwave_frontend.optimizer.plan_node.plan_base depends on risingwave_common.catalog.schema✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node.plan_base → type in risingwave_common.catalog.schema) reference.
risingwave_frontend.optimizer.plan_node.plan_base uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_frontend.optimizer.plan_node.plan_base, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
32→34 risingwave_frontend.optimizer.plan_node.plan_base depends on risingwave_frontend.optimizer.plan_nodecycle✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node.plan_base → type in risingwave_frontend.optimizer.plan_node) reference.
risingwave_frontend.optimizer.plan_node.plan_base uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_frontend.optimizer.plan_node.plan_base, not the reverse.
Position
Above the diagonal — a cycle. Neither module can be changed, tested or deployed independently until one of these dependencies goes.
33→9 risingwave_frontend.optimizer.plan_node.utils depends on risingwave_common.util.epoch✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node.utils → type in risingwave_common.util.epoch) reference.
risingwave_frontend.optimizer.plan_node.utils uses risingwave_common.util.epoch. Changing risingwave_common.util.epoch can break risingwave_frontend.optimizer.plan_node.utils, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
33→13 risingwave_frontend.optimizer.plan_node.utils depends on risingwave_frontend.catalog.table_catalog✕
Type pairs
2 distinct (type in risingwave_frontend.optimizer.plan_node.utils → type in risingwave_frontend.catalog.table_catalog) references.
risingwave_frontend.optimizer.plan_node.utils uses risingwave_frontend.catalog.table_catalog. Changing risingwave_frontend.catalog.table_catalog can break risingwave_frontend.optimizer.plan_node.utils, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
33→17 risingwave_frontend.optimizer.plan_node.utils depends on risingwave_sqlparser.ast✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node.utils → type in risingwave_sqlparser.ast) reference.
risingwave_frontend.optimizer.plan_node.utils uses risingwave_sqlparser.ast. Changing risingwave_sqlparser.ast can break risingwave_frontend.optimizer.plan_node.utils, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
33→22 risingwave_frontend.optimizer.plan_node.utils depends on risingwave_common.types✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node.utils → type in risingwave_common.types) reference.
risingwave_frontend.optimizer.plan_node.utils uses risingwave_common.types. Changing risingwave_common.types can break risingwave_frontend.optimizer.plan_node.utils, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
33→24 risingwave_frontend.optimizer.plan_node.utils depends on risingwave_common.catalog.column✕
Type pairs
2 distinct (type in risingwave_frontend.optimizer.plan_node.utils → type in risingwave_common.catalog.column) references.
risingwave_frontend.optimizer.plan_node.utils uses risingwave_common.catalog.column. Changing risingwave_common.catalog.column can break risingwave_frontend.optimizer.plan_node.utils, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
33→26 risingwave_frontend.optimizer.plan_node.utils depends on risingwave_common.catalog.schema✕
Type pairs
3 distinct (type in risingwave_frontend.optimizer.plan_node.utils → type in risingwave_common.catalog.schema) references.
risingwave_frontend.optimizer.plan_node.utils uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_frontend.optimizer.plan_node.utils, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
34→4 risingwave_frontend.optimizer.plan_node depends on risingwave_frontend.optimizer.plan_node.expr_visitable✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node → type in risingwave_frontend.optimizer.plan_node.expr_visitable) reference.
risingwave_frontend.optimizer.plan_node uses risingwave_frontend.optimizer.plan_node.expr_visitable. Changing risingwave_frontend.optimizer.plan_node.expr_visitable can break risingwave_frontend.optimizer.plan_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
34→5 risingwave_frontend.optimizer.plan_node depends on risingwave_meta.manager.notification✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node → type in risingwave_meta.manager.notification) reference.
risingwave_frontend.optimizer.plan_node uses risingwave_meta.manager.notification. Changing risingwave_meta.manager.notification can break risingwave_frontend.optimizer.plan_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
34→11 risingwave_frontend.optimizer.plan_node depends on risingwave_frontend.optimizer.plan_node.expr_rewritable✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node → type in risingwave_frontend.optimizer.plan_node.expr_rewritable) reference.
risingwave_frontend.optimizer.plan_node uses risingwave_frontend.optimizer.plan_node.expr_rewritable. Changing risingwave_frontend.optimizer.plan_node.expr_rewritable can break risingwave_frontend.optimizer.plan_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
34→18 risingwave_frontend.optimizer.plan_node depends on risingwave_frontend.optimizer.plan_node.convert✕
Type pairs
4 distinct (type in risingwave_frontend.optimizer.plan_node → type in risingwave_frontend.optimizer.plan_node.convert) references.
risingwave_frontend.optimizer.plan_node uses risingwave_frontend.optimizer.plan_node.convert. Changing risingwave_frontend.optimizer.plan_node.convert can break risingwave_frontend.optimizer.plan_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
34→19 risingwave_frontend.optimizer.plan_node depends on risingwave_frontend.optimizer.plan_node.plan_tree_node✕
Type pairs
2 distinct (type in risingwave_frontend.optimizer.plan_node → type in risingwave_frontend.optimizer.plan_node.plan_tree_node) references.
risingwave_frontend.optimizer.plan_node uses risingwave_frontend.optimizer.plan_node.plan_tree_node. Changing risingwave_frontend.optimizer.plan_node.plan_tree_node can break risingwave_frontend.optimizer.plan_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
34→26 risingwave_frontend.optimizer.plan_node depends on risingwave_common.catalog.schema✕
Type pairs
1 distinct (type in risingwave_frontend.optimizer.plan_node → type in risingwave_common.catalog.schema) reference.
risingwave_frontend.optimizer.plan_node uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_frontend.optimizer.plan_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
34→32 risingwave_frontend.optimizer.plan_node depends on risingwave_frontend.optimizer.plan_node.plan_base✕
Type pairs
3 distinct (type in risingwave_frontend.optimizer.plan_node → type in risingwave_frontend.optimizer.plan_node.plan_base) references.
risingwave_frontend.optimizer.plan_node uses risingwave_frontend.optimizer.plan_node.plan_base. Changing risingwave_frontend.optimizer.plan_node.plan_base can break risingwave_frontend.optimizer.plan_node, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
35→3 risingwave_stream.task.actor_manager depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_stream.task.actor_manager → type in risingwave_expr_impl.scalar.format) reference.
risingwave_stream.task.actor_manager uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_stream.task.actor_manager, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
35→6 risingwave_stream.task.actor_manager depends on risingwave_stream.executor.monitor.streaming_stats✕
Type pairs
2 distinct (type in risingwave_stream.task.actor_manager → type in risingwave_stream.executor.monitor.streaming_stats) references.
risingwave_stream.task.actor_manager uses risingwave_stream.executor.monitor.streaming_stats. Changing risingwave_stream.executor.monitor.streaming_stats can break risingwave_stream.task.actor_manager, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
35→7 risingwave_stream.task.actor_manager depends on risingwave_common.bitmap✕
Type pairs
2 distinct (type in risingwave_stream.task.actor_manager → type in risingwave_common.bitmap) references.
risingwave_stream.task.actor_manager uses risingwave_common.bitmap. Changing risingwave_common.bitmap can break risingwave_stream.task.actor_manager, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
35→10 risingwave_stream.task.actor_manager depends on risingwave_frontend.handler.explain_analyze_stream_job.graph✕
Type pairs
1 distinct (type in risingwave_stream.task.actor_manager → type in risingwave_frontend.handler.explain_analyze_stream_job.graph) reference.
risingwave_stream.task.actor_manager uses risingwave_frontend.handler.explain_analyze_stream_job.graph. Changing risingwave_frontend.handler.explain_analyze_stream_job.graph can break risingwave_stream.task.actor_manager, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
35→29 risingwave_stream.task.actor_manager depends on risingwave_batch.executor✕
Type pairs
4 distinct (type in risingwave_stream.task.actor_manager → type in risingwave_batch.executor) references.
risingwave_stream.task.actor_manager uses risingwave_batch.executor. Changing risingwave_batch.executor can break risingwave_stream.task.actor_manager, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
36→2 risingwave_connector.source.base depends on risingwave_dml.txn_channel✕
Type pairs
1 distinct (type in risingwave_connector.source.base → type in risingwave_dml.txn_channel) reference.
risingwave_connector.source.base uses risingwave_dml.txn_channel. Changing risingwave_dml.txn_channel can break risingwave_connector.source.base, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
36→3 risingwave_connector.source.base depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_connector.source.base → type in risingwave_expr_impl.scalar.format) reference.
risingwave_connector.source.base uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_connector.source.base, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
36→21 risingwave_connector.source.base depends on risingwave_common.types.jsonb✕
Type pairs
1 distinct (type in risingwave_connector.source.base → type in risingwave_common.types.jsonb) reference.
risingwave_connector.source.base uses risingwave_common.types.jsonb. Changing risingwave_common.types.jsonb can break risingwave_connector.source.base, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
36→22 risingwave_connector.source.base depends on risingwave_common.types✕
Type pairs
1 distinct (type in risingwave_connector.source.base → type in risingwave_common.types) reference.
risingwave_connector.source.base uses risingwave_common.types. Changing risingwave_common.types can break risingwave_connector.source.base, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
36→31 risingwave_connector.source.base depends on risingwave_connector.sink✕
Type pairs
1 distinct (type in risingwave_connector.source.base → type in risingwave_connector.sink) reference.
risingwave_connector.source.base uses risingwave_connector.sink. Changing risingwave_connector.sink can break risingwave_connector.source.base, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
36→34 risingwave_connector.source.base depends on risingwave_frontend.optimizer.plan_node✕
Type pairs
1 distinct (type in risingwave_connector.source.base → type in risingwave_frontend.optimizer.plan_node) reference.
risingwave_connector.source.base uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_connector.source.base, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
37→17 risingwave_frontend.handler depends on risingwave_sqlparser.ast✕
Type pairs
3 distinct (type in risingwave_frontend.handler → type in risingwave_sqlparser.ast) references.
risingwave_frontend.handler uses risingwave_frontend.session. Changing risingwave_frontend.session can break risingwave_frontend.handler, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
37→27 risingwave_frontend.handler depends on risingwave_expr.expr✕
Type pairs
1 distinct (type in risingwave_frontend.handler → type in risingwave_expr.expr) reference.
risingwave_frontend.handler uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_frontend.handler, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
38→10 risingwave_frontend.stream_fragmenter depends on risingwave_frontend.handler.explain_analyze_stream_job.graph✕
Type pairs
2 distinct (type in risingwave_frontend.stream_fragmenter → type in risingwave_frontend.handler.explain_analyze_stream_job.graph) references.
risingwave_frontend.stream_fragmenter uses risingwave_frontend.handler.explain_analyze_stream_job.graph. Changing risingwave_frontend.handler.explain_analyze_stream_job.graph can break risingwave_frontend.stream_fragmenter, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
38→34 risingwave_frontend.stream_fragmenter depends on risingwave_frontend.optimizer.plan_node✕
Type pairs
1 distinct (type in risingwave_frontend.stream_fragmenter → type in risingwave_frontend.optimizer.plan_node) reference.
risingwave_frontend.stream_fragmenter uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_frontend.stream_fragmenter, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
39→27 risingwave_object_store.object.sim.service depends on risingwave_expr.expr✕
Type pairs
1 distinct (type in risingwave_object_store.object.sim.service → type in risingwave_expr.expr) reference.
risingwave_object_store.object.sim.service uses risingwave_expr.expr. Changing risingwave_expr.expr can break risingwave_object_store.object.sim.service, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
39→34 risingwave_object_store.object.sim.service depends on risingwave_frontend.optimizer.plan_node✕
Type pairs
1 distinct (type in risingwave_object_store.object.sim.service → type in risingwave_frontend.optimizer.plan_node) reference.
risingwave_object_store.object.sim.service uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_object_store.object.sim.service, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
40→3 risingwave_stream.executor depends on risingwave_expr_impl.scalar.format✕
Type pairs
1 distinct (type in risingwave_stream.executor → type in risingwave_expr_impl.scalar.format) reference.
risingwave_stream.executor uses risingwave_expr_impl.scalar.format. Changing risingwave_expr_impl.scalar.format can break risingwave_stream.executor, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
40→6 risingwave_stream.executor depends on risingwave_stream.executor.monitor.streaming_stats✕
Type pairs
3 distinct (type in risingwave_stream.executor → type in risingwave_stream.executor.monitor.streaming_stats) references.
risingwave_stream.executor uses risingwave_stream.executor.monitor.streaming_stats. Changing risingwave_stream.executor.monitor.streaming_stats can break risingwave_stream.executor, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
40→9 risingwave_stream.executor depends on risingwave_common.util.epoch✕
Type pairs
1 distinct (type in risingwave_stream.executor → type in risingwave_common.util.epoch) reference.
risingwave_stream.executor uses risingwave_common.util.epoch. Changing risingwave_common.util.epoch can break risingwave_stream.executor, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
40→22 risingwave_stream.executor depends on risingwave_common.types✕
Type pairs
2 distinct (type in risingwave_stream.executor → type in risingwave_common.types) references.
risingwave_stream.executor uses risingwave_common.catalog.schema. Changing risingwave_common.catalog.schema can break risingwave_stream.executor, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
40→27 risingwave_stream.executor depends on risingwave_expr.expr✕
Type pairs
2 distinct (type in risingwave_stream.executor → type in risingwave_expr.expr) references.
risingwave_stream.executor uses risingwave_frontend.optimizer.plan_node. Changing risingwave_frontend.optimizer.plan_node can break risingwave_stream.executor, not the reverse.
Position
Below the diagonal — points down the layering, which is what you want.
Findings mapped to OWASP categories; the specific CVEs/secrets are in the Security dimension cards below and findings.md (redacted only on the public version of this report).
OWASP category
Findings
Severity
A03:2021 — Injection
129
High / Critical
A05:2021 — Security Misconfiguration
111
High / Critical
A06:2021 — Vulnerable & Outdated Components
46
High / Critical
A02:2021 — Cryptographic Failures
6
High / Critical
Roadmap
Immediately resolve the four leaked secrets in configuration and script files to eliminate critical exposure risks. Strengthen system reliability by enforcing timeouts, retries, and circuit breakers on all outbound HTTP calls, while cleaning up unused dependencies to reduce the attack surface. Finally, establish documented disaster recovery procedures with clear recovery targets and enable security scanning on pull requests to prevent regressions before they merge.
Ranked by impact ÷ effort. "Helps" is the estimated gain on the 0–100 health score.
Do this
Helps
Effort
Dimension
Resolve the 4 Leaked secret finding(s) in REDACTED Scanning — start with REDACTED, REDACTED, REDACTED.
Bound every outbound call: pass `signal: AbortSignal.timeout(ms)` to `fetch`, set `timeout` on the axios instance (`axios.create({ timeout })`), and add retries with back-off (`axios-retry`, `p-retry`) and a breaker (`opossum`, `cockatiel`) around dependencies that fail.
Every finding carries one of four grades. Three say how serious it is. The fourth says this
survey could not settle it — and it is a grade, not a gap.
Critical — 278
A definite problem that already costs you something and drags the score down: a
missing authorisation check, a dependency with a known exploit, a build that does not reproduce. Failure here
tends to cause failures elsewhere.
Serious — 2936
Likely wrong, but not failing yet. It degrades
the codebase over a longer horizon and can cause failures elsewhere — not urgent this week, not something to
carry for two years either.
Minor — 47
Recorded, with no effect on how the codebase functions.
Present so the survey is complete, not because it needs doing.
Could not be resolved — 41
Something this survey could not settle
from the outside, and which could be critical or serious. Either a control was required and no
positive evidence of it exists in the repository — a backup job that nothing shows was ever restored from proves
nothing about restores — or our own analysis could not run over that part of the tree. This is not a clean
result. These are excluded from the score rather than awarded a pass, so the number on the cover neither
rewards nor penalises them: if you act on this survey without resolving them, you carry that risk yourself. Each
one is named under Limitations.
Methodology & how to trust this report
Watchdog is a deep, periodic assessment — run each sprint, monthly, or quarterly, taking the time to go wider and deeper than a quick check and surfacing in one coherent report what you'd otherwise piece together from a dozen separate tools. It scores deterministically: the same commit yields the same score, every run. 62 of 67 evaluated dimensions are computed purely by tools and static analysis (confidence 1.0); 5 documentation/naming judgement(s) are LLM-assisted and labelled advisory. Overall confidence is 0.9 — the weighted average across measured dimensions; it falls as more of the score leans on LLM-assisted judgement and rises when it's fully tool-backed.
Every figure here is one of three kinds, and we label which: ✓ Measured — a deterministic fact (LoC, complexity, coverage); ~ Modeled — an estimate from a stated model (cost, effort, value-at-risk), always a range with its assumptions, never a precise fact; ◐ Advisory — an LLM prose judgement. We never present a modelled estimate as if it were measured. Perfect or absent scores carry their provenance too (ADR-0011): ✓ Tool-verified means the property itself was measured across the surface; ○ Nothing flagged means the probes came back clean — a claim bounded by what a repository can show; ⊘ Not evidenced means a working control (a tested restore, an automated rollback) showed no positive evidence — absence of evidence is not evidence of a control, so it's excluded from the score rather than awarded a spurious 10; ◐ Sampled · advisory marks an LLM verdict over a bounded sample — advisory, never a deterministic measurement.
What we checked — 67 dimensions across the health lenses
Each chip is a dimension scored from real signals across architecture, testing, dependencies, security & compliance, documentation, git-history and code quality — in one coherent pass. A surface report typically covers a handful.
How to trust any code-health report — three questions
Can you open the finding? Real findings cite a repo-relative file and line you can open at the cited line — never an absolute scratch path. Here, 3202 of 3261 do; the remainder are repo-wide signals — a dimension-level measurement, not a single line. (Every path in this report is repo-relative by construction: paths are normalized at the producer and the report is rejected if any rooted path leaks through.)
Is there a tool behind the number? Every score below names the method that produced it — Roslyn, git, a scanner, or (for a handful of documentation/naming dimensions) an LLM labelled sampled · advisory — not a narrative.
Does re-running give the same result? Run it again on the same commit and the score — and this report, byte for byte — is identical. A report whose numbers move between runs is describing the run, not the code.
This report answers yes to all three. That's the bar to hold any assessment to.
Tools & methods
The actual versions used this run (captured at analysis time) — re-run on the same commit for the identical score.
Method
Backs
Version
Evaluator
Roslyn static analysis
Complexity, cohesion, coupling, dead code, API surface, layering
What ran differently this time — a tool absent, degraded, or that fell back to an estimate. Named openly, not folded silently into the scores. A degraded run also records its exact cause in diagnostics.md.
D6 Cohesion (LCOM4) — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check's reader does not cover the language this repository's product is written in, so it had nothing of the product to read. That is a gap in this analyzer's language reach — not a finding about this repository.
D10 Test Quality — measured, with a gap in what it reached — Watchdog measured this, but not all of it. What it did not reach is a gap on our side — a collector, parser or image we have not built yet — so the numbers on that dimension cover less than the repository, and the part left out is not evidence that it would have passed. The 2 test(s) behind this row are the ones the C# collector could read, and this repository also carries at least 247 test source file(s) (.java, .rs, .ts) that it cannot: it parses C# syntax and matches C# test attributes, so a vitest/jest/JUnit/pytest-style suite is invisible to it. Skipped tests, zero-assertion tests and the other quality signals on this row are UNMEASURED in that suite — their absence from the counts above is a gap in this analyzer's language coverage, not a finding that those tests are sound.
D11 Test Reliability — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. Test reliability NOT SCORED: this repository's production source spans .rs, and the built-in reliability runner cannot re-run the .rs test suite(s) — so reliability was not measured for the repository as a whole. The .NET suite did build and re-run, and came back with 0 flaky across 2 measured tier(s) (other: measured (0 flaky); JavaScript/TypeScript (mocha via `npm install --ignore-scripts` (no lockfile) in integration_tests/client-library/nodejs/ (1 tests); jest via `npm install --ignore-scripts` (no lockfile) in src/utils/pgwire/tests/js/ (0 tests)): measured (0 flaky)) — but that is a figure for one half of the product, and we do not publish a partial one as if it were complete. This is OUR limitation, not a defect in the repo — test reliability is excluded from the score rather than counted.
D14 License Compliance — measured, with a gap in what it reached — Watchdog measured this, but not all of it. What it did not reach is a gap on our side — a collector, parser or image we have not built yet — so the numbers on that dimension cover less than the repository, and the part left out is not evidence that it would have passed. This repository declares a Cargo manifest, but the licence verdict published here was taken over its NuGet package dependencies. Nothing was read about its Cargo dependencies' licensing in either direction, and a clean score on this card must not be read as covering them.
D14 License Compliance — measured, with a gap in what it reached — Watchdog measured this, but not all of it. What it did not reach is a gap on our side — a collector, parser or image we have not built yet — so the numbers on that dimension cover less than the repository, and the part left out is not evidence that it would have passed. This repository declares a Python pyproject.toml/requirements.txt (pip/uv/Poetry), but the licence verdict published here was taken over its NuGet package dependencies. Nothing was read about its Python dependencies' licensing in either direction, and a clean score on this card must not be read as covering them.
D14 License Compliance — measured, with a gap in what it reached — Watchdog measured this, but not all of it. What it did not reach is a gap on our side — a collector, parser or image we have not built yet — so the numbers on that dimension cover less than the repository, and the part left out is not evidence that it would have passed. This repository declares a Maven POM, but the licence verdict published here was taken over its NuGet package dependencies. Nothing was read about its Maven dependencies' licensing in either direction, and a clean score on this card must not be read as covering them.
D14 License Compliance — measured, with a gap in what it reached — Watchdog measured this, but not all of it. What it did not reach is a gap on our side — a collector, parser or image we have not built yet — so the numbers on that dimension cover less than the repository, and the part left out is not evidence that it would have passed. This repository declares package.json, but the licence verdict published here was taken over its NuGet package dependencies. Nothing was read about its npm dependencies' licensing in either direction, and a clean score on this card must not be read as covering them.
D15 Churn × Complexity Hotspots — measured, with a gap in what it reached — Watchdog measured this, but not all of it. What it did not reach is a gap on our side — a collector, parser or image we have not built yet — so the numbers on that dimension cover less than the repository, and the part left out is not evidence that it would have passed. A hotspot's complexity is meant to be the worst body its churn actually touched. For src/common/src/system_param/mod.rs, src/storage/backup/src/meta_snapshot_v2.rs that could not be established — the complexity reader for the file reports no body extents, or the history carries no per-line attribution — so the row quotes the file's worst body, which the counted changes may never have touched. The churn count is unaffected.
D17 Explicit Debt — measured, with a gap in what it reached — Watchdog measured this, but not all of it. What it did not reach is a gap on our side — a collector, parser or image we have not built yet — so the numbers on that dimension cover less than the repository, and the part left out is not evidence that it would have passed. The 2 deducted marker(s) and the 0.2/KLoC density on this row were taken over this repository's .NET projects ALONE: .rs (723,009 lines, 93% of production source) went unread, because every marker collector on this path is reached through a C# workspace. A read-only sweep of that source finds at least 1,013 task marker(s) (TODO/FIXME/HACK/XXX) across 552 file(s) that this score does not count — a floor, since only line comments are read there and D17's other eight marker kinds (suppressions, NoWarn, editorconfig severities, empty catches, commented-out code, Obsolete, dead code, preprocessor branches) need a compiler we do not have for that language. The debt in that source is UNMEASURED — its absence from the score above is a gap in this analyzer's language coverage, not a finding that the code carries none.
D39 IL Efficiency — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. IL NOT MEASURED: the analyzer's own build of this repository failed for an ENVIRONMENT reason (exit 1) — MSBuild's engine or the CLR gave up, or our image does not carry the SDK band/targeting pack this repository needs. This is OUR limitation, not a defect in the repo, and it is not a statement that this repository fails to build. D18 owns the question of whether this repository builds; it was not answered here.
AX1 Captive dependencies — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
AX2 Stateful singletons — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
AX6 Interface segregation — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is computed over the public interfaces this run's compilations declare, and none was loaded, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
C1 Data Protection — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. These personal data controls are read from declarative annotations, request middleware, entity/column names and guard methods in a C# source model, and none was loaded on this run, so there was nothing to gather. That is a gap in this analyzer's language reach — not a finding that the repository lacks personal data controls.
C2 Access Controls — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. These authorization controls are read from declarative annotations, request middleware, entity/column names and guard methods in a C# source model, and none was loaded on this run, so there was nothing to gather. That is a gap in this analyzer's language reach — not a finding that the repository lacks authorization controls.
C3 Audit Trail — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. These audit controls are read from declarative annotations, request middleware, entity/column names and guard methods in a C# source model, and none was loaded on this run, so there was nothing to gather. That is a gap in this analyzer's language reach — not a finding that the repository lacks audit controls.
C4 Data Retention — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. These retention controls are read from declarative annotations, request middleware, entity/column names and guard methods in a C# source model, and none was loaded on this run, so there was nothing to gather. That is a gap in this analyzer's language reach — not a finding that the repository lacks retention controls.
C5 Data-Subject Rights — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. These data-subject rights controls are read from declarative annotations, request middleware, entity/column names and guard methods in a C# source model, and none was loaded on this run, so there was nothing to gather. That is a gap in this analyzer's language reach — not a finding that the repository lacks data-subject rights controls.
ED5 Idempotency — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check finds retry-prone mutations by walking the repository's declared types, and NONE was loaded on this run, so it had nothing to look at. That is a limit of the analyzer's reach — it reads .NET projects — not a finding that this repository has no command handlers or message consumers.
GD1 Unfinished & placeholder code — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
P8 Schema migrations — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. The schema may be created by a runner, a deploy script or a config file outside what this check reads, so an absence here is our blind spot rather than a missing migration strategy. The card abstains instead of scoring. You can widen what we reach: if the schema is created and evolved by a tool this check does not name, naming it lets us teach the detector to read it.
PF1 Benchmark discipline — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
PF2 Allocation hygiene — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X1 Async correctness — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X12 Unreachable branch — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X13 Undrained process stream — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X14 Bypassable address classification — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X15 Unvalidated length from an untrusted reader — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X16 Unfloored truncation loop — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X17 Uncapped recursion over a caller-supplied document — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X18 Disposal-pattern correctness — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X19 Unrestored process-global state — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X2 Cancellation propagation — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X20 Mistyped argument guard — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X21 Side-effecting pattern guard — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X22 Contradicted release guard — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X23 Unguarded diagnostic materialisation — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X24 Document value interpolated into markup unescaped — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X25 Inert configuration knob — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X26 Unsynchronised callback handoff — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X27 Collection changed while being enumerated — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X28 Index access outside its own emptiness guard — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X29 Per-element action decided by a fixed element — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X3 Exception handling — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X30 Support guard that admits what it rejects — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X32 Type resolved by simple name across every loaded assembly — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X4 Structured logging — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
X5 Nullable reference types — not measured this run — Watchdog could not measure this here. That is a gap on our side — a collector, parser or image we have not built yet — and it is neither a defect in this repository nor evidence that the check would have passed. This check is implemented over the C# syntax tree, and no C# was loaded on this run, so it had nothing to read. That is a gap in this analyzer's language reach — not a finding that the repository is free of what this check looks for.
Repo exclusion declarations: 21 pattern(s) declared (.gitattributes linguist-generated/vendored, .editorconfig generated_code) excluded 0 source file(s) from code-quality scoring. Declarations are the repo's own visible statement that a tree is machine-written or vendored — auditable in any diff, honored by GitHub the same way.
Limitations & what we did not check
Watchdog assesses the repository exactly as committed, and only the repository. By design it does not reach outside the source tree: the live cloud account, the running CI/CD pipeline, the host's branch-protection and approval rules, the production configuration, or a restore actually exercised against a backup are all out of scope. That boundary is a feature, not a gap — a repo-relative, deterministic scan re-runs identically on any commit and every finding opens at a real file and line, where a live audit can neither be reproduced nor traced. The visible consequence is that controls which leave no in-repo evidence are reported as "not evidenced" and excluded from the score rather than awarded a number a static scan cannot justify.
Per-dimension blind spots
For each dimension that was measured, what a static, repo-only scan structurally cannot see — the honest edge of the measurement, not a failure of it.
D1 Cyclomatic Complexity: Cyclomatic complexity counts branches statically — it cannot tell an essential decision tree from accidental tangle, nor see complexity that lives in data or configuration (large switch-case token tables, DSL lexers/parsers, data-as-code rule tables) rather than control flow: a tokenizer's many single-character cases read as high complexity though each branch is trivial.
D2 Cognitive Complexity: Cognitive-complexity heuristics approximate how hard code is to follow; genuine domain difficulty and well-named intent that eases reading are not captured.
D3 God Classes: "God class" is sized by members and responsibilities visible in the type — a deliberately broad facade over a coherent subsystem can read the same as an accidental grab-bag. For front-end JS the file-length check is cohesion-aware (a single-responsibility module — one class/IIFE — earns a 3× threshold), but cohesion is approximated from top-level declarations, not true dependency structure.
D4 Code Duplication: Duplication is token-similarity — an in-process token-stream comparison over sliding windows, with type-aware normalization — so it finds copy-paste, not semantic duplication expressed differently. Committed machine-written code (scaffolded migrations, designer/codegen output, protobuf/OpenAPI stubs, model snapshots) is EXCLUDED — its repetition is the tool's, not the team's — so the score reflects hand-written duplication only.
D5 Coupling: Coupling is measured between projects/assemblies — runtime coupling through DI, reflection, messaging or shared databases is invisible to a static reference graph.
D9 Test Distribution: The test-pyramid shape is inferred from project/folder naming and references, with a single test host bucketed per-file by its path tier and content signals — a suite that names tiers unconventionally and gives no per-file signal can still be mis-bucketed.
D10 Test Quality: Assertion density is structural — it cannot tell a meaningful behavioural assertion from a trivial one, only that an assertion is present.
D12 Dependency Hygiene: Dependency health reads manifests and lockfiles — a vulnerability in a vendored/copied dependency, or risk from how a dependency is actually used, is outside this view.
D13 REDACTED Scanning: REDACTED detection is signature- and entropy-based on the current tree — a secret that does not match a known pattern, or one already rotated, will not be flagged (a clean scan is "nothing matched", not "no secrets exist").
D14 License Compliance: License compatibility is checked against declared package metadata and a policy — mislabelled or missing license metadata, and obligations that depend on how you distribute, are not resolved here.
D15 Churn × Complexity Hotspots: Churn hotspots come from git history — a freshly imported or squashed repository has no churn signal, and recent rewrites can mask a historically risky file.
D16 Bus Factor: Bus-factor is a time-decayed model of commit attribution (who has recently, repeatedly worked a file), not comprehension — pairing, review and reading-without-committing spread knowledge it can't see; bot commits and shared accounts still distort it.
D17 Explicit Debt: Acknowledged-debt signals (TODO/FIXME, suppressions, dead code) are textual — undocumented debt that nobody marked, and debt that lives in design rather than annotations, is invisible. Committed machine-written code (scaffolded migrations, designer/codegen output, generated stubs) is excluded — it is never the team's dead code to delete.
D19 Documentation Quality: Documentation quality is judged by an LLM over a bounded sample of docs — it reads what is written, not whether the docs match the running system, and it is advisory, not a measurement. Its critique rows are drawn from a closed category vocabulary and each row means the same thing in every run, so two scans can be compared row by row; the SET that fires is still a sample, and does not repeat exactly. Measured on one frozen input, six scans at one engine SHA: 2-5 critique rows per scan, 8 distinct rows across the six, 3 of those 8 seen in only one scan. So a D19 row is evidence about the documentation, but a COUNT of D19 rows is not a quantity — never read a change in it as an improvement or a regression.
D21 Naming Consistency: Naming quality is an LLM judgement over a bounded sample — it assesses clarity/consistency of the names it sees, not domain-correctness, and is advisory.
D22 Internal API Consistency: API-surface coherence is an LLM judgement over a sample of the public surface — consistency of intent across the whole API is approximated, not exhaustively verified.
D24 Comment Value: Comment value (WHY vs WHAT) is an LLM judgement over a bounded sample — it is advisory and cannot weigh a comment against the precise code change it was written to explain.
D26 Project Cohesion: Project focus is sized from members/namespaces per project — a project that is broad by deliberate design reads the same as one that has sprawled.
D28 Secrets (history): Secret-history scanning sweeps the git log for known patterns — a secret that predates the available history, or never matched a signature, is not found (clean means "nothing matched in the history we can see").
D29 Static Analysis (SAST): SAST findings are pattern-based (semgrep) — it finds classes of bug it has rules for; logic flaws, auth/authorization gaps and issues needing runtime context are out of reach (and clean means "no rule matched").
D30 Dependency Vulnerabilities: CVE matching depends on accurate package/version metadata and on the advisory databases — a vulnerability with no published advisory, or in code not declared as a dependency, is not seen. Coverage needs a RESOLVED graph: an unpinned requirements.txt, or a pom without a resolved build, yields partial coverage rather than a clean verdict. An ecosystem the analyzer cannot scan is reported as unmeasured, never as clean.
D31 IaC & Container Security: IaC scanning checks Dockerfiles/Terraform/Kubernetes against best-practice rules — it cannot see the live cloud account, runtime configuration, or drift between the committed config and what is actually deployed.
D34 Knowledge Freshness: Freshness is decayed commit RECENCY, not comprehension — code read often but rarely committed reads as orphaned, and stable code that genuinely needs no changes is penalised the same as forgotten code; bot/squash commits distort it like the bus factor.
D35 Change Coupling: Change coupling is co-change in COMMITS — files split across separate commits, or coupled only through a shared config/build step, read as uncoupled, and a sweeping commit (rename/format) is excluded so it doesn't couple everything. It shows that files change together, not WHY: a high coupling can be a healthy cohesive pair as readily as a hidden leak.
D43 Malicious Dependencies: Only packages some vulnerability database has already NAMED as malicious are seen — a compromise published in the last hours, or never reported at all, is invisible here, and this dimension reading 10 is not evidence that a dependency is trustworthy. There is no typosquat or dependency-confusion analysis: a package nobody has reported is simply absent from the feeds. Coverage is the dependency scan's: an ecosystem that could not be scanned is disclosed as unmeasured, never as clean.
D44 Platform End-of-Life: The support table is FROZEN, so it goes out of date by losing RECALL: a release that ended support after the table was written is missed until the table is refreshed, and this dimension reading 10 is not evidence that a platform is current. Only platforms the repository DECLARES in a place this pass reads are seen — a runtime named only in a REDACTED (D31's subject), in a CI workflow (D29's), or in a file this pass does not parse (go.mod, a Gemfile ruby directive) is invisible here, which is why a repository declaring none of them abstains rather than scoring. Only frameworks with a PUBLISHED support policy are tracked: React, Flask and Express publish none, so their age cannot be judged and their absence from a report is not a statement that they are supported.
AC2 Forms & labels: Label association is read from static markup — a label wired up at runtime (JS-set aria-labelledby, framework-injected ids) reads as missing, a present label says nothing about whether its text is correct. A known UI-library field component (e.g. a JSX <TextField>) is now checked conservatively — flagged only when it carries NO label/aria-label/aria-labelledby/id/name — but wrapper/context-labelled libraries (Chakra/Radix FormControl+FormLabel) aren't statically visible (possible false positive) and non-JSX lowercased components are still skipped. A click handler on a plain element is now asked for a name too (it is a control the author declared), but the subtree test that answers it is deliberately generous: any DYNAMIC text expression in the subtree counts as a name, so an icon chosen by a ternary ({cond ? <IconA/> : <IconB/>}) reads as named, and a glyph component from a library the icon-import list does not know still names its parent. A clean result is "no unlabelled control found", not a labelling proof.
AC3 Page structure: Page structure is read from the static markup tree — landmarks, headings and lang injected at runtime aren't seen, heading ORDER is checked structurally (not against the rendered visual hierarchy), and lang/title/main fire only on full documents, never partials, and the data-table check sees header-cell presence (a <th> exists), not whether each header correctly associates with its cells. Static readiness, not conformance.
AC5 ARIA correctness: ARIA correctness is checked against the static role/attribute shape — roles/attributes set dynamically aren't seen, a valid role says nothing about whether it matches the element's real behaviour, and required-state checks are suppressed when a JSX spread could supply them. The two-branch toggle check (a control whose state is conveyed only by which of two mutually exclusive branches renders) reads CONDITIONALS THAT ARE ATTRIBUTES — Vue v-if/v-else/v-show and Alpine x-if/x-show — so the same toggle written as a Svelte {#if} block or a JSX ternary is control flow the markup model never projects as a branch and is not seen at all.
AC6 Visual & motion safety: Contrast and motion safety are PARTIAL by construction — literal colours (hex/rgb/hsl/named) in inline styles, in-repo <style> blocks, in-repo .css files, var() tokens, Tailwind neutral utilities and CSS-in-JS top-level declarations are read (same-rule/same-element colour+background pairs only); computed/runtime/theme colour, external-CDN stylesheets, CSS-in-JS dynamic (${…}) and nested-selector colours, cross-element pairs and image contrast stay out of reach, so a clean result is bounded by what the static CSS itself shows.
AC7 A11y enforcement: Enforcement is scored from in-repo config/CI evidence only — an a11y gate enforced in external tooling with no in-repo trace can't be credited, and a configured linter is presence, not proof the rules actually run or block a merge.
AX10 Code composition: Role is inferred from namespace/folder convention, not semantics — a domain concept living in a folder named "Services" reads as application, and the split is lines-of-code, not business value. The business-logic-share score is a SOFT, FLOORED signal: it contributes to the Architecture lens but is floored at the Critical gate, so an infrastructure-heavy design (a gateway, an ETL, a driver) is legitimately low without being nuked to zero.
AX9 CQS / query purity: Handlers are found by interface/name convention — a query handler using neither is not seen. Mutation is a resolved write/publish invocation (SaveChanges/repository/bus), so a write hidden behind a hand-rolled wrapper, reflection, or a string-keyed service locator resolves to a non-persistence type and isn't flagged; it detects that a query writes state, not whether the write is a legitimate read-side cache update. Clean means "no resolved write/publish in a query body", not a proof of CQS purity.
DM4 Rich vs anemic domain model: Behaviour is detected as state mutation inside a method body — a method that enforces an invariant by validating-and-throwing without mutating reads as a query, and mutation delegated through an interface the scan can't resolve isn't credited; entities with zero public properties still drop out of the population. It detects that state changes, not whether the rule is correct.
DM6 Domain ↔ infrastructure boundary: Infrastructure reached through a hand-rolled wrapper, a domain-named facade, reflection, or a string-keyed service locator resolves to a non-infra type and isn't seen; the body scan is symbol resolution over syntax, not full dataflow. A clean result means "no resolved infra reference in a domain body", not a proof of purity.
M4 Documentation accuracy: Onboarding quality is an LLM read of the docs/setup present — it cannot run the onboarding or measure how long a real new joiner takes; the verdict is sampled and advisory.
P4 Deployment & Rollback: Approval/branch-protection rules live in repository settings the scan cannot see — only their in-repo evidence (config files, workflows) is checked, so a control enforced purely in the host's settings reads as "not evidenced".
P5 DR & Backup: Backup/restore and disaster-recovery readiness is judged from in-repo evidence — a config that exists is not a tested restore, so the absence of positive evidence is reported as "not evidenced", never scored as present.
P6 Release Hygiene: Rollback/observability controls are inferred from repo artefacts (pipelines, dashboards-as-code) — controls configured in external tooling, with no in-repo trace, cannot be credited.
The LLM boundary
LLM-set scores this run (5): D19, D21, D22, D24, M4 (model: Local LLM). For these, a model reads a bounded sample and sets the numeric score; each names its own sample and method on its card. They are sampled and advisory by design: they vary at the margins between runs and are never a deterministic measurement. Every other score in this report is tool-computed at confidence 1.0.
What it measures: How tangled the control flow is — methods with many branches are hard to test and change.
Method: Cyclomatic complexity per method (1 + decision points), computed exhaustively across production source; test projects separated by convention. Deterministic.
329 method(s) exceeded the cyclomatic complexity threshold of 15; the worst was risingwave_frontend::handler::handle at 181. A further 97 method(s) were over the threshold but excluded as flat dispatchers (a long switch/match over independent cases: many branches, almost no nesting), the largest being PostgresErrorCode::sqlstate at 258 — they are counted neither in the figure above nor in this dimension's score. 45 files carry no cyclomatic complexity row at all for this reason — every one of their over-threshold methods was excluded, so the exclusion is disclosed nowhere in the file itself: src/error/src/code.rs (PostgresErrorCode::sqlstate at 258), src/frontend/src/datafusion/scalar_function/convert.rs (risingwave_frontend::datafusion::scalar_function::convert::convert_trivial_datafusion_func at 71), src/connector/src/source/cdc/external/postgres.rs (risingwave_connector::source::cdc::external::postgres::type_name_to_pg_type at 52), src/connector/src/connector_common/postgres.rs (risingwave_connector::connector_common::postgres::sea_type_to_pg_type at 50), src/common/src/array/arrow/arrow_impl.rs (FromArrow::from_array at 39), and 40 more not listed here. They are named here because the per-file figures other dimensions report are taken BEFORE this exclusion, so such a file can show a high maximum complexity elsewhere in this report and nothing here, with nothing to reconcile the two.
+ 170 more group(s) — more in Appendix A; the complete list is findings.md.
What to do
Resolve the 29 risingwave_frontend finding(s) in Cyclomatic Complexity — start with REDACTED (3), create_source.rs (3), show.rs (2). — One of this dimension's main actionable groups (29 warning-level).
Resolve the 16 risingwave_connector finding(s) in Cyclomatic Complexity — start with debezium.rs (4), mysql.rs (2), create_table.rs (2). — One of this dimension's main actionable groups (16 warning-level).
Resolve the 16 Parser finding(s) in Cyclomatic Complexity — start with parser.rs (15), statement.rs. — One of this dimension's main actionable groups (16 warning-level).
Enforce Cyclomatic Complexity in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Prevented — provenance only; does not change the score.
Detailed fixes: d1_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: How hard the code is for a person to follow, beyond raw branching.
Method: Cognitive complexity per method (Sonar-style nesting-penalized score), computed exhaustively over production code, excluding test projects. Deterministic.
+ 353 more group(s) — more in Appendix A; the complete list is findings.md.
What to do
Resolve the 48 risingwave_frontend finding(s) in Cognitive Complexity — start with create_source.rs (4), create_table.rs (4), func.rs (3). — One of this dimension's main actionable groups (48 warning-level).
Resolve the 23 Parser finding(s) in Cognitive Complexity — start with parser.rs (22), statement.rs. — One of this dimension's main actionable groups (23 warning-level).
Resolve the 21 Binder finding(s) in Cognitive Complexity — start with REDACTED (4), table_or_source.rs (3), match_recognize.rs (2). — One of this dimension's main actionable groups (21 warning-level).
Enforce Cognitive Complexity in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Prevented — provenance only; does not change the score.
Detailed fixes: d2_recommendation.md · top locations in Appendix A, every location in findings.md.
Do you agree with this assessment?
D3 · God Classes7.7 / 10Strong✓ Tool-verified
What it measures: Over-large classes that try to do too much ("god classes").
Method: God-class detection by line and method-count thresholds per logical type (partial classes unified), filtered for generated code and registration/contract false positives. Deterministic.
+ 2 more group(s) — more in Appendix A; the complete list is findings.md.
What to do
Resolve the 231 MethodTooLong finding(s) in God Classes — start with REDACTED (18), streaming_job.rs (6), ddl_controller.rs (5). — One of this dimension's main actionable groups (231 warning-level).
Resolve the 199 FileTooLong finding(s) in God Classes — start with REDACTED (23), lib.rs (4), utils.rs (3). — One of this dimension's main actionable groups (199 warning-level).
Resolve the 90 FunctionTooLong finding(s) in God Classes — start with REDACTED (8), create_table.rs (5), create_source.rs (4). — One of this dimension's main actionable groups (90 warning-level).
Enforce God Classes in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Prevented — provenance only; does not change the score.
Detailed fixes: d3_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Copy-pasted code that should be shared instead.
Method: Code duplication via token-stream sliding windows with type-aware normalization (locals masked, type names preserved), density-scored per KLoC of production code. Deterministic.
919 duplicated block group(s) detected. A further 44 rows report members as variants of one another; they aggregate block groups already counted above and are not themselves counted. 66 of the 963 are in trees this repository does not ship — vendored, example/demo, fixture and benchmark code — and are ranked below the shipped groups rather than excluded from them: the duplication there is real and is still counted in this dimension's score. The dimensions that publish a production-file census leave those trees out of theirs, so this count is deliberately drawn over the wider population.
+ 196 more group(s) — more in Appendix A; the complete list is findings.md.
What to do
Resolve the 63 Duplicated block (8 lines × 2) finding(s) in Code Duplication — start with REDACTED (4), lib.rs (2), ddl_service.rs (2). — One of this dimension's main actionable groups (63 warning-level).
Resolve the 54 Duplicated block (14 lines × 2) finding(s) in Code Duplication — start with server_pb.rs (5), REDACTED (3), streaming_job.rs (2). — One of this dimension's main actionable groups (54 warning-level).
Resolve the 51 Duplicated block (7 lines × 2) finding(s) in Code Duplication — start with clickhouse.rs (3), orderby.rs (2), utils.rs (2). — One of this dimension's main actionable groups (51 warning-level).
Enforce Code Duplication in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Verified — provenance only; does not change the score.
Detailed fixes: d4_recommendation.md · top locations in Appendix A, every location in findings.md.
Do you agree with this assessment?
D5 · Coupling8.4 / 10Strong✓ Tool-verified
What it measures: Whether volatile projects sit underneath others that depend on them (so their churn ripples upward), and whether project dependencies form cycles. A widely-depended-on but stable shared/kernel project is healthy, not penalised.
Method: Dependency cycles via elementary-DFS over real .csproj references, plus Martin instability (afferent/efferent) per project. Exhaustive over the reference graph, deterministic.
Coverage: Exhaustive · type-level: afferent/efferent coupling + cycles computed over every production type — the population is all types, not a name convention.
81 production modules (Maven+Cargo), 0 dependency cycle(s), 7 unstable depended-on module(s). Read from the build's own module declarations; 9 module(s) off the main sequence, with abstractness counted on 64 of the 81 (the rest declare no modelled class or interface, export only macros, or have no source directory of their own).
Off the main sequence: delta_btree_map · ×9
Unstable project risingwave_cmd
Unstable project risingwave_compute
Unstable project risingwave_ctl
Unstable project risingwave_frontend
+ 3 more group(s) — more in Appendix A; the complete list is findings.md.
What to do
Resolve the 9 Off the main sequence finding(s) in Coupling. — One of this dimension's main actionable groups (9 warning-level).
Resolve the 1 Unstable project risingwave_cmd finding(s) in Coupling. — One of this dimension's main actionable groups (1 warning-level).
Resolve the 1 Unstable project risingwave_compute finding(s) in Coupling. — One of this dimension's main actionable groups (1 warning-level).
Enforce Coupling in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Prevented — provenance only; does not change the score.
Detailed fixes: d5_recommendation.md · top locations in Appendix A, every location in findings.md.
Do you agree with this assessment?
D9 · Test Distribution10.0 / 10Exemplary✓ Tool-verified
What it measures: Whether the test suite has a healthy mix of unit / integration / end-to-end tests.
Method: Test projects classified (Unit/Integration/BDD/E2E) from compiled metadata; test methods counted exhaustively across projects with placement-agnostic disk fallback. Deterministic.
3408 test methods: 3030 unit, 378 integration, 0 BDD, 0 e2e. The JavaScript/TypeScript suite contributes 2 `it`/`test` case(s) across 1 test file(s) declaring at least one beside 2 .NET test method(s); its tier split is read from package names and paths only. The Rust suite contributes 3346 `#[test]` function(s) across 762 file(s) declaring at least one; its unit/integration split is Cargo's own — 67 of those file(s) are integration-test targets under a crate's tests/ directory, and the rest are #[test] functions compiled into the crate they test. The Python suite contributes 12 test function(s) across 2 file(s) declaring at least one — every `def test…` in a file pytest or unittest would collect, which is those frameworks' own definition of a case; a parametrize table counts once, so this is a floor. Its tier split is read from file names and paths only. The Go suite contributes 2 test case(s) across 2 `_test.go` file(s) declaring at least one — every `func Test…(t *testing.T)` that `go test` would collect, plus the suite methods a testify-style runner reaches; a table-driven case list counts once, so this is a floor. Its tier split is INFERRED from file names, paths and build constraints, not declared: 2 of those file(s) use Go's external test package (`package x_test`), which is a visibility boundary rather than a pyramid tier and was not read as one. The java suite(s) contribute 44 test method(s), read from the language model's own test census — every XCTest `test…` method on an XCTestCase, every swift-testing `@Test` and every JUnit/TestNG `@Test`-annotated method, which is those frameworks' own discovery rule. Their tier split is INFERRED from the test target's name and path only, not declared.
✓ On the Gold path — maintain.
Detailed fixes: d9_recommendation.md.
Do you agree with this assessment?
D10 · Test Quality8.1 / 10Strong✓ Tool-verified
What it measures: Whether the tests truly assert behaviour rather than just running the code.
Method: Per-test assertions, skips, and mock references analyzed via Roslyn; structured skip-reason tags (BUG:/ENV:) separate documented deferrals from debt. Deterministic.
0 skipped, 1 zero-assertion, no mocking-framework packages referenced (hand-written doubles or no mocking) across 2 tests. Measured on the C# suite only — at least 247 test source file(s) (.java, .rs, .ts) went unread, so its test quality is unmeasured and is not in these counts.
No assertions: CreateAndReadFromTableintegration_tests/client-library/csharp/NpgsqlTest.cs:12
What to do
Resolve the 1 No assertions finding(s) in Test Quality — start with NpgsqlTest.cs. — One of this dimension's main actionable groups (1 warning-level).
Enforce Test Quality in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Prevented — provenance only; does not change the score.
Detailed fixes: d10_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether dependencies are current, secure, and not bloated.
Method: Manifest scan via dotnet list package across all projects; worst-signal-per-package deduction (saturating for vulnerabilities, capped-linear for deprecation/outdated) per KLoC. Exhaustive, deterministic.
13 outdated, 1 author-deprecated direct Go module(s), 0 pinning or checksum defect(s). Whether any of these modules is UNMAINTAINED is not graded — proxy.golang.org publishes no maintenance status, and release age does not stand in for one. Whether any is UNUSED is not graded either: that is a source question, not a registry one. Known CVEs in this module graph are D30's question, read from go.mod and go.sum there.
Deprecated module: github.com/aws/aws-sdk-go
Outdated: github.com/Shopify/sarama · ×13
What to do
Resolve the 1 Deprecated module finding(s) in Dependency Hygiene. — One of this dimension's main actionable groups (1 warning-level).
Detailed fixes: d12_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether any secrets (keys, tokens, passwords) have leaked into the code.
Method: In-process native secret scanner (entropy plus signature patterns) across all tracked files; no external tool. A clean result is a measured 10, not no-data zero. Deterministic.
Resolve the 4 Leaked secret finding(s) in REDACTED Scanning — start with REDACTED, REDACTED, REDACTED. — One of this dimension's main actionable groups (4 issue-level).
Enforce REDACTED Scanning in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Prevented — provenance only; does not change the score.
Detailed fixes: d13_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether the licenses of third-party packages are compatible with your policy.
Method: Third-party package licenses resolved from declared package metadata and checked against the configured policy (allow/deny/copyleft). Deterministic; clean = no incompatible license found at metadata depth.
0 of 114 packages use a banned license. ★ DEPTH: this repository's MSBuild projects declare 5 direct `PackageReference`(s), and 109 further package(s) were reached beyond them by closing the graph over nuget.org's own nuspec dependency graph — so a banned licence pulled in only by a dependency's OWN dependencies is inside this verdict. A package whose licence nuget.org could not be asked for is not graded, and version ranges are taken at their lower bound, so this is the closure as that graph states it rather than a restored consumer's exact resolution. ★ COVERAGE OF THIS VERDICT: it grades this repository's NuGet package dependencies and nothing else. The repository also declares a Cargo manifest, a Python pyproject.toml/requirements.txt (pip/uv/Poetry), a Maven POM and package.json, and the licences of those dependency graphs were NOT read by this pass — a gap in this engine's coverage, not a statement about them. So this result says the graded closure carries no banned licence; it does NOT say this repository's licensing is clear.
What it measures: Files that change often and are also complex — the riskiest hotspots.
Method: Per production file churn times cyclomatic complexity over a rolling window, computed from git and Roslyn/JS/Razor analysis. Exhaustive, deterministic per commit date.
Top hotspots: src/meta/src/barrier/checkpoint/state.rs (15×79=1185); src/sqlparser/src/ast/mod.rs (7×148=1036); src/frontend/src/handler/mod.rs (5×181=905) Repeated repair below the complexity floor: src/meta/src/barrier/schedule.rs (7 of 12 changes were fixes); src/meta/node/src/lib.rs (6 of 10 changes were fixes); src/meta/src/manager/env.rs (6 of 7 changes were fixes)
Resolve the 72 Hotspot finding(s) in Churn × Complexity Hotspots — start with REDACTED (12), config.rs (2), create_table.rs (2). — One of this dimension's main actionable groups (72 warning-level).
Resolve the 14 Repeated repair finding(s) in Churn × Complexity Hotspots — start with REDACTED (2), recovery.rs (2), schedule.rs. — One of this dimension's main actionable groups (14 warning-level).
Detailed fixes: d15_recommendation.md · top locations in Appendix A, every location in findings.md.
Do you agree with this assessment?
D16 · Bus Factor9.7 / 10Exemplary✓ Tool-verified
What it measures: Whether knowledge is concentrated in too few people (the "bus factor").
Method: Living knowledge per author via time-decayed commit attribution (6-month half-life, focus weighting) across largest source files. Deterministic, avoids blame's mechanical-refactor false positives.
70 source file(s) have their living knowledge concentrated in one author (≥90% of recent, decayed contribution). The largest is src/stream/src/executor/backfill/snapshot_backfill/executor.rs. Counted over 2006 of the 2876 production source files in this repository: the rest are under the ~2,400-byte size floor this dimension measures over.
Off-boarding risk: anonymized user #1 · ×8
Further sole-owners (lower concentration)
✓ On the Gold path — maintain.
Detailed fixes: d16_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Acknowledged debt left in the code — TODOs, dead code, suppressed warnings.
Method: Roslyn syntactic debt markers (suppressions/TODO/FIXME/HACK/empty-catch/commented-code/Obsolete) plus SymbolFinder dead-code analysis; weighted-debt-per-KLoC density deducted 2.0x per unit. Deterministic, exhaustive.
2 deducted debt markers + 0 dead symbols across 0 LoC in the .NET projects (0.2/KLoC) → score 9.7. Measured on the .NET source only: .rs (93% of production source) was not read, and carries at least 1,013 uncounted task marker(s) in 552 file(s).
Resolve the 1 TodoComment finding(s) in Explicit Debt — start with NpgsqlTest.cs. — One of this dimension's main actionable groups (1 warning-level).
Resolve the 1 CommentedOutCode finding(s) in Explicit Debt — start with sink_option.yml. — One of this dimension's main actionable groups (1 warning-level).
Enforce Explicit Debt in CI to reach Verified (currently Documented). — Hardens enforcement from Documented toward Prevented — provenance only; does not change the score.
Detailed fixes: d17_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether the project's documentation is clear, complete, and useful.
Method: Judged by language model at low temperature (0.0-0.1) on a deterministic doc sample (READMEs plus first 25 architecture docs), with two-pass stability filtering. Advisory, sampled.
The repository's READMEs are well-structured and complete for their respective directories: the ci/ldap-test/, ci/mongodb-tls/, develop/sql_bench/, docs/dev/, and e2e_test/* directories each document what they contain with clear directory structures, prerequisites, test execution, and run commands. The root README (docs/rustdoc/) is a repository-wide guide that documents the developer guide source, build process, and rustdoc index page, which is ideal for an overview but does not cover installation or usage of the actual RisingWave software. (10 of 25 sampled documents could not be assessed: 1 of 2 evaluation groups failed.)
Documentation: no architecture or design documentationci/mongodb-tls/README.md
✓ On the Gold path — maintain.
Detailed fixes: d19_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether names — types, methods, variables — are clear and consistent.
Method: Judged by language model at low temperature (0.0-0.1) on a deterministic random symbol sample (fixed size, not exhaustive), with disclosed confidence band. Advisory, sampled.
0 naming inconsistencies across 3 sampled symbols.
✓ On the Gold path — maintain.
Detailed fixes: d21_recommendation.md.
Do you agree with this assessment?
D22 · Internal API ConsistencyStronggated by 2 serious findings◐ Sampled · advisory
What it measures: Whether the internal API surface is consistent and coherent.
Method: Judged by language model at low temperature over a sample of the public API surface (IsPackable or .Contracts types). Sampled, advisory; confidence discounted by model uncertainty.
2 API inconsistencies across a 400-member sample of 3146 exposed types.
Inconsistent access to metrics: `BatchTaskContext` provides a unified `batch_metrics()` method returning a composite `BatchMetrics` object, while `BatchEnvironment` exposes individual metric components (executor, manager, spill) as separate methods. This forces consumers to know whether they are interacting with a Task Context or an Environment to access metrics, and requires different code paths to get the same data.
Redundant/Confusing cancellation checks: `check()` returns a `Result` (likely checking for abort/cancel state), while `cancelled()` and `is_cancelled()` both appear to return boolean status. `cancelled()` and `is_cancelled()` are semantically identical, and `check()` overlaps in intent but differs in return type, creating confusion about which method to use for a simple boolean check.
What to do
Resolve the 1 Inconsistent access to metrics finding(s) in Internal API Consistency. — One of this dimension's main actionable groups (1 warning-level).
Resolve the 1 Redundant/Confusing cancellation checks finding(s) in Internal API Consistency. — One of this dimension's main actionable groups (1 warning-level).
Detailed fixes: d22_recommendation.md · top locations in Appendix A, every location in findings.md.
Do you agree with this assessment?
D24 · Comment ValueWeak◐ Sampled · advisory
What it measures: Whether comments are worth it — explaining WHY (valuable) rather than WHAT (redundant).
Method: Judged by language model at low temperature (0.0-0.1) on deterministically sampled inline comments with surrounding code; findings verified back to sampled comments by substring match. Advisory, sampled.
Resolve the 5 redundant comment finding(s) in Comment Value — start with NpgsqlTest.cs (5). — One of this dimension's main actionable groups (5 recommendation-level).
Detailed fixes: d24_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether any secrets were ever committed — scanned across the full git history, not just now.
Method: REDACTED scan via TWO gitleaks detect passes in an isolated checkout — the full git history, then a second --no-git pass over the working tree as it stands — merged and de-duplicated by (rule, file, line); each match flagged High. Both invocations are recorded in the audit trail. Exhaustive; when the tool is absent, or when its output cannot be parsed into the expected shape, the dimension is WITHHELD as an explicit measurement gap on our side — unscored and excluded from the lens, never a hedged middling score.
1 finding(s): 0 critical, 1 high, 0 medium, 0 low. Remediation for historically-committed secrets is credential rotation — they remain in history regardless of later deletion.
REDACTED
REDACTED
What to do
Resolve the 1 REDACTED finding(s) in Secrets (history) — start with REDACTED. — One of this dimension's main actionable groups (1 issue-level).
Resolve the 1 Rotate the exposed credentials finding(s) in Secrets (history). — One of this dimension's main actionable groups (1 recommendation-level).
Detailed fixes: d28_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Real static-analysis (SAST) findings — likely security bugs in the code, any language.
Method: Polyglot static analysis via semgrep across the repo using the pinned, image-baked p/security-audit + p/owasp-top-ten rulesets (no scan-time registry fetch); severity rules (ERROR/WARNING/INFO) map to a full-band severity-weighted score. Exhaustive, deterministic; degrades on parse failure.
Coverage: semgrep pattern rules over all files — exhaustive for the rule set, blind to classes of bug without a rule (clean = no rule matched).
129 finding(s): 0 critical, 106 high, 15 medium, 8 low. 66 unpinned-GitHub-Actions row(s) are reported here but scored by D36 (supply-chain provenance), which measures that posture as `pinned_actions` — one pinning decision is charged once, not once per lens. semgrep hit a parse error in 17 file(s) — `REDACTED` (lines 127–138, lines 138–155), `src/batch/src/error.rs` (line 39), `src/common/src/array/data_chunk.rs` (line 382, line 417, line 441, …), `src/common/src/array/stream_chunk.rs` (lines 278–332, line 388, line 396, …), `src/connector/src/sink/log_store.rs` (lines 133–138), … (+12 more) — so no absence of findings in the named regions is evidence of anything; rows reported elsewhere in those files are real. Fix the syntax error (or exclude the file deliberately) and re-scan to cover them. Separately, one or more rules could not re-parse an embedded snippet in 9 file(s) (e.g. a workflow `run:` block read as shell). Those files WERE scanned and their other rows are unaffected; only those rules' view of those snippets is missing.
REDACTED
REDACTED
REDACTED
REDACTED
REDACTED
+ 16 more group(s) — more in Appendix A; the complete list is findings.md.
What to do
Resolve the 19 REDACTED finding(s) in Static Analysis (SAST) — start with REDACTED (2), REDACTED (2), REDACTED (2). — One of this dimension's main actionable groups (19 issue-level).
Resolve the 6 REDACTED finding(s) in Static Analysis (SAST) — start with REDACTED, REDACTED, REDACTED. — One of this dimension's main actionable groups (6 issue-level).
No action in Static Analysis (SAST) — all 66 REDACTED finding(s) are reported here at file:line but scored by D36 (supply-chain provenance), so none is charged to this dimension. — One of this dimension's main actionable groups (66 issue-level, 0 of them charged here).
Detailed fixes: d29_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether any dependency has a known published vulnerability (CVE), direct or transitive, in ANY ecosystem the repository declares — Dart pub, Elixir and Erlang via Hex, Go modules, Java and Kotlin via Maven/Gradle, JavaScript/npm, .NET/NuGet, PHP/Composer, Python/PyPI, RubyGems, Rust/Cargo and Swift.
Method: Dependency-CVE scan across every ecosystem the repository declares, scored ONCE. Three sources are unioned and deduplicated by advisory identity (rule id + alias closure, CVE<->GHSA) scoped to package+version, keeping the worst severity: `osv-scanner --recursive` over osv.dev for Dart pub, Elixir/Hex (and Erlang, whose `rebar.lock` syft first converts to a CycloneDX SBOM the scanner reads, with rows attributed back to the lock), Go, Java and Kotlin via Maven/Gradle, npm, PHP/Composer, Python/PyPI, RubyGems, Rust/Cargo and Swift; `trivy fs --scanners vuln` for npm lockfiles; and `dotnet list package --vulnerable --include-transitive` for NuGet (with per-advisory collapse of the project x target-framework fan-out), plus a DECLARED-dependency arm that resolves a published gem's gemspec against rubygems.org where no Gemfile.lock is committed. `SeverityScore(c,h,m,l, normalizer 8.0)`. NotApplicable only when NO ecosystem is readable; if any applicable ecosystem could not be scanned the findings are REPORTED and the score is withheld. Supersedes the npm and OSV arms, retired 2026-09-05.
+ 2 more group(s) — more in Appendix A; the complete list is findings.md.
What to do
Resolve the 13 Medium advisory (unmaintained) finding(s) in Dependency Vulnerabilities — start with REDACTED (13). — One of this dimension's main actionable groups (13 warning-level).
Resolve the 12 Medium advisory (unsound) finding(s) in Dependency Vulnerabilities — start with REDACTED (12). — One of this dimension's main actionable groups (12 warning-level).
Resolve the 7 High CVE finding(s) in Dependency Vulnerabilities — start with REDACTED (4), REDACTED (3). — One of this dimension's main actionable groups (7 issue-level).
Detailed fixes: d30_recommendation.md · top locations in Appendix A, every location in findings.md.
Resolve the 59 High IaC finding(s) in IaC & Container Security — start with REDACTED (21), REDACTED (13), REDACTED (10). — One of this dimension's main actionable groups (59 issue-level).
Resolve the 51 Medium IaC finding(s) in IaC & Container Security — start with REDACTED (29), REDACTED (8), REDACTED (5). — One of this dimension's main actionable groups (51 warning-level).
Resolve the 1 Low IaC finding(s) in IaC & Container Security — start with REDACTED. — One of this dimension's main actionable groups (1 recommendation-level).
Detailed fixes: d31_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether anyone still has living knowledge of each file, or it has been orphaned — last understood long ago by someone now gone quiet. The sibling of the bus factor: D16 asks who owns it, D34 asks whether anyone still knows it.
Method: File orphaning as total living-knowledge decay below one focused-commit's worth within a year, computed per-file from the D16 decay model. Exhaustive, deterministic over fixed history.
433 of 2006 significant source file(s) are orphaned — their living knowledge has decayed to nothing, so no one currently understands them. The largest is src/meta/src/stream/stream_graph/assignment.rs. Counted over 2006 of the 2876 production source files in this repository: the rest are under the ~2,400-byte size floor this dimension measures over.
Resolve the 17 Orphaned knowledge finding(s) in Knowledge Freshness — start with lib.rs (2), assignment.rs, PostgresConnectorConfig.java. — One of this dimension's main actionable groups (17 issue-level).
Resolve the 1 Further orphaned files (smaller) finding(s) in Knowledge Freshness. — One of this dimension's main actionable groups (1 recommendation-level).
Detailed fixes: d34_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether files that change together actually belong together — pairs that repeatedly co-change in git history despite having no explicit code dependency, surfacing the hidden/logical coupling (and boundaries in the wrong place) a static scan can't see.
Method: Pairwise co-occurrence over the per-commit file sets in git history (production source only — tests and generated dropped): Degree-of-Coupling = shared ÷ min individual revisions, reported above noise floors (each file ≥10 revisions, ≥5 shared commits, ≥50% strength); sweeping commits excluded. Deterministic over fixed history.
Coverage: Population: PRODUCTION source files only — test and generated files are dropped before pairing, so a class co-changing with its own test (trivially ~100%) can't drown the real production↔production coupling. Pairs ranked by Degree-of-Coupling. A non-source file is never a coupling PARTICIPANT either: documentation, schemas, config and data files are dropped with the rest, so a code↔docs pair — a command and the reference page that restates it — is not reported however strongly the two co-change; nor is coupling that runs THROUGH a build step or config file.
Resolve the 77 Boundary-crossing change coupling finding(s) in Change Coupling — start with hummock_service.rs (6), risingwave-dev-dashboard.dashboard.py (5), alter_streaming_rate_limit.rs (4). — One of this dimension's main actionable groups (77 issue-level).
Resolve the 46 Change coupling finding(s) in Change Coupling — start with stream_hash_agg.rs (2), alter_table_with_sr.rs (2), control.rs (2). — One of this dimension's main actionable groups (46 warning-level).
Resolve the 11 Change-coupling hub finding(s) in Change Coupling — start with REDACTED (2), panic_store.rs, traced_store.rs. — One of this dimension's main actionable groups (11 warning-level).
Detailed fixes: d35_recommendation.md · top locations in Appendix A, every location in findings.md.
What it measures: Whether the build pipeline provides supply-chain integrity — generated provenance/attestation, signed artifacts (cosign/sigstore), an SBOM, and pinned build actions. Presence of the configuration, not a runtime guarantee.
Method: Supply-chain provenance/signing read deterministically from CI/build config (.github/workflows, .gitlab-ci.yml, azure-pipelines, Jenkinsfile, .circleci) + the release surface: four signals — generated provenance/attestation (SLSA/in-toto/actions-attest), artifact signing (cosign/sigstore/gitsign), an SBOM (syft/sbom-action/*.spdx.json/*.cdx.json), and SHA-pinned build actions — scored 10·present/denom. NotApplicable without a build pipeline. Detects configuration presence, not runtime enforcement.
What it measures: Whether the repository publishes a coordinated-vulnerability-disclosure policy (SECURITY.md or security.txt) with a reporting contact, so finders know how to report a vulnerability. Presence of a policy file with a contact, not whether the policy is adequate or honoured.
Method: Vulnerability-disclosure policy read deterministically from the repo: a SECURITY.md (root/.github/docs) or .well-known/security.txt / security.txt, regex-checked for a reporting contact (email / URL / mailto). Present + contact → 10; present without a contact → 4; NotApplicable when no policy file exists (it may live off-repo). Detects the policy file's presence + contact, not its adequacy.
What it measures: Whether any dependency the repository declares is published as MALICIOUS rather than merely vulnerable — a package that is an attacker's work, in any ecosystem osv-scanner reads. Scored apart from D30 because the answer is binary: there is no safe version to upgrade to, and the fix is to remove the package and rotate every credential it could have read.
Method: The same dependency scan D30 reads, partitioned on the scanner's own classification rather than rescanned: a row is MALICIOUS when its id is in the `MAL-` space (the ossf/malicious-packages feed) OR its `database_specific.cwe_ids` carries `CWE-506` ("Embedded Malicious Code"). Both channels are structural; the summary text is deliberately NOT read, because a malicious-package record whose summary says only "Critical severity vulnerability" is a real shape ([GHSA redacted]) and a text matcher misses it. Scored BINARY: any surviving row is 0, whatever its severity and however many CVEs sit beside it — a hostile dependency is not a quantity. Applicability and degradation are D30's: NotApplicable only when no ecosystem is readable, and an unscannable ecosystem degrades rather than reading clean. SCORED, not informational.
What it measures: Whether anyone still ships security patches for the platform this repository RUNS ON — the runtime it pins and the framework majors its own constraints hold it to. Separate from D12 because the question differs: a current Django on an end-of-life Python is perfectly up to date and completely unsupported, and the fix is a migration rather than a version bump. What the repository says it merely SUPPORTS is never charged.
Method: End-of-life PLATFORM read from the repository's own declarations and graded against a FROZEN, dated table of vendor support dates — no network, no feed, no API, so this dimension answers identically inside a closed scan fence. Two subjects: a RUNTIME the project pins (a single or all-end-of-life TargetFramework, a .nvmrc or .python-version, a requires-python CAP) and a FRAMEWORK major a dependency constraint cannot move off (a caret, tilde or exact version; `vue@^2.7.16` pins Vue 2). A FLOOR is deliberately never charged — `requires-python = ">=3.8"` states what a package SUPPORTS, not what it runs on — and a multi-target project is charged only when EVERY target is out of support. Runtime 4.0/product capped 8.0, framework 1.5 capped 4.5. The table is safe to freeze because a statement about support that ended in the past cannot become false: it loses recall as it ages, never precision, and a test asserts every entry predates the freeze date. Disjoint from D31 (a container image's OS layer) and D29 (the toolchain a CI workflow installs). Abstains when the repository declares no platform this pass reads — never scores it clean.
0 end-of-life runtime(s) and 0 end-of-life framework(s), read from 15 platform declaration(s) and 89 dependency declaration(s). This dimension reads what the repository says about ITSELF — a pinned target framework, a version file, a capped requires-python, a Rust toolchain pin, a framework major a constraint cannot move off. A FLOOR is deliberately never charged: `requires-python = ">=3.8"` states what the package SUPPORTS, not what it runs on, and a well-maintained library declares exactly that while running its own CI on a current release. The end-of-life facts are FROZEN and dated, so this dimension needs no network and answers identically inside a closed scan fence; as the table ages it loses recall and never precision, because a statement about support that ended in the past cannot become false. The OS layer of a container image is D31's question and the toolchain a CI workflow installs is D29's; this row is neither.
✓ On the Gold path — maintain.
Detailed fixes: d44_recommendation.md.
Do you agree with this assessment?
Frontend & cross-cutting dimensions
R = React/JS · M = Maturity · P = Readiness.
AC2 · Forms & labels4.3 / 10Weak✓ Tool-verified
Other · Accessibility — Whether form controls have a programmatic label (an associated label, aria-label or aria-labelledby), buttons have text, links have an accessible name, a click handler on a plain element names the control it declares, fieldsets have a non-empty legend, known UI-library field components carry a label prop, and a placeholder isn't used as the only label. Static markup readiness, not a WCAG conformance claim.
Method: Static markup-model scan: inputs/selects/textareas checked for an associated label[for]/wrapping label/aria-label/aria-labelledby (per document), buttons for accessible text, fieldsets for a legend; placeholder-only labelling flagged. Deterministic, hard fact per control.
Coverage: Population: form controls, buttons, links, fieldsets and known UI-library field components in the PARSED MARKUP files only (.html/.htm/.cshtml/.razor/.vue/.svelte/.jsx/.tsx); components, hidden subtrees and spread/dynamic-attribute elements are skipped, so a control whose label arrives through a spread or a runtime expression is deliberately not judged. Markup built in script — tagged-template (html`…`) UIs and hyperscript DOM factories — is not read at all.
This UI-library field component has no label / aria-label / aria-labelledby / id / name, and nothing it renders carries one either. The text inside it does not stand in for one: these compound APIs render a trigger with role="combobox" (or role="button"), and those roles take their name from the AUTHOR, not from their content — so the words on screen never reach the accessibility tree as a name. Name it whichever way this library supports: a label prop, an aria-label, or an id on the rendered control with a <label htmlFor> pointing at it. For a group of controls, name the group itself (aria-label, or a fieldset with a legend) — labelling each item leaves the set unnamed. (×2) — dashboard/pages/await_tree.tsx:120, dashboard/pages/fragment_graph.tsx:411
This UI-library field component has no label / aria-label / aria-labelledby / id / name — and neither does anything it renders — so it likely renders an unlabelled control. Name it whichever way this library supports: a label prop, an aria-label, or an id on the rendered control with a <label htmlFor> pointing at it. For a group of controls, name the group itself (aria-label, or a fieldset with a legend) — labelling each item leaves the set unnamed. — dashboard/pages/cpu_profiling.tsx:199
What to do
Give every control a programmatic label (a <label for> / wrapping <label> / aria-label) and every button text — a placeholder is not a label.
Other · Accessibility — Whether pages declare a language (well-formed BCP-47) and a non-empty title, expose exactly one main landmark and a sane heading order with non-empty headings, keep zoom enabled, title their iframes, give data tables header cells, and avoid meta-refresh. Static markup readiness, not a WCAG conformance claim.
Method: Static markup-model scan: html lang, document <title>, a main landmark and heading order on full documents only, plus zoom-disabling viewports, untitled iframes and meta-refresh anywhere. Deterministic, per structural checkpoint.
Coverage: Population: the PARSED MARKUP documents (.html/.htm/.cshtml/.razor/.vue/.svelte/.jsx/.tsx). The page-level checks — lang, title, single main landmark — fire ONCE PER FULL DOCUMENT (an <html> root) and never on a partial or component fragment, so a repo of fragments is assessed only on the per-element checks (heading order, table headers, iframe titles, meta-refresh, zoom). Markup built in script — tagged-template (html`…`) UIs and hyperscript DOM factories — is not read at all.
Other · Accessibility — Whether ARIA is used correctly — valid non-abstract roles, the ARIA state a role requires, valid (non-misspelled) aria-* attribute names, in-enum values for token-typed aria-* attributes, and no aria-hidden on (or wrapping) a focusable element. Static markup readiness, not a WCAG conformance claim.
Method: Static markup-model scan: role values checked against the WAI-ARIA role set (abstract/invalid flagged), required ARIA state for a role, and aria-hidden on a focusable element. Deterministic, role/attribute level.
Coverage: Population: elements in the PARSED MARKUP files (.html/.htm/.cshtml/.razor/.vue/.svelte/.jsx/.tsx) that carry a role or an aria-* attribute; roles and token values are checked against the ARIA enums exhaustively within that set. An expression-valued (dynamic) role or aria-* value is skipped rather than guessed, and markup built in script — tagged-template (html`…`) UIs and hyperscript DOM factories — is not read at all.
Other · Accessibility — Whether focus outlines aren't removed without a replacement, motion respects prefers-reduced-motion, and literal CSS colour pairs meet contrast — PARTIAL: inline styles, in-repo <style> blocks, in-repo .css files, var() tokens, Tailwind neutral utilities and CSS-in-JS literals are read (hex/rgb/hsl/named), never computed/runtime/external-CDN colour. Static markup readiness, not a WCAG conformance claim.
Method: Static markup/CSS scan: inline outline:none/0, literal inline colour/background contrast against the 4.5:1 AA floor, and <style>-block animation without a prefers-reduced-motion guard. Deterministic but PARTIAL — only inline styles and in-repo CSS literals are visible.
Coverage: Population: styled elements in the PARSED MARKUP files (.html/.htm/.cshtml/.razor/.vue/.svelte/.jsx/.tsx), plus in-repo <style> blocks, in-repo .css files and CSS-in-JS literals. Colour contrast is computed from LITERAL colour pairs only (hex/rgb/hsl/named, including var() tokens and Tailwind neutral utilities) — computed, runtime-themed and external-CDN colour is never resolved, so this is a partial read of contrast by construction. Markup built in script — tagged-template (html`…`) UIs and hyperscript DOM factories — is not read at all.
Do you agree with this assessment?
AC7 · A11y enforcement4.0 / 10Weak✓ Tool-verified
Other · Accessibility — Whether accessibility is ENFORCED in the toolchain — an accessibility checker configured over the markup (an a11y lint rule set, e.g. eslint-plugin-jsx-a11y or vuejs-accessibility where the project lints JavaScript) and an automated accessibility assertion wired into tests or CI (axe/pa11y/Lighthouse or an equivalent) — on the Documented→Verified→Prevented ladder.
Method: Repo config/CI scan: an accessibility checker configured over the markup (an a11y lint rule set such as eslint-plugin-jsx-a11y / vuejs-accessibility where JavaScript is linted) and an automated accessibility assertion in tests or CI (axe/pa11y/Lighthouse or equivalent), graded on the Documented→Verified→Prevented rungs. Deterministic, presence/rung detection.
Coverage: Population: the repository's own tooling configuration — lint config, test and CI files — NOT the markup. It is read for a configured accessibility checker and an automated accessibility assertion (axe/pa11y/Lighthouse, or a native-toolkit equivalent), and it credits an INVOCATION, never a mention: a licence filename, an import comment or a doc reference earns no rung. Enforcement configured entirely outside the repository leaves no evidence here and cannot be credited.
No accessibility enforcement found — no a11y linter (eslint-plugin-jsx-a11y) and no axe/pa11y/Lighthouse in tests or CI. Start with the linter to catch issues at author time. What was searched, so you can tell an absence from a miss: the 24 markup file(s) this pass actually assessed, the linter configuration checked in beside them, and this repository's test and CI files — matched by name against the accessibility checkers this dimension carries. An audit run outside the repository, a hosted scanner, or a check whose name is not one of those, is not seen here.
What to do
Enforce accessibility in the toolchain: add eslint-plugin-jsx-a11y, then assert with jest-axe in tests, then gate axe/pa11y/Lighthouse in CI.
Other · Architecture — How the codebase splits by code ROLE — domain, application, infrastructure, test, generated. The significance map behind the knowledge/coupling weighting, and a DDD signal in its own right: a thin domain core under fat infrastructure is the anemic-domain smell, quantified. How each file's role is decided, because the split is only as good as that: a generated name or a build-output tree makes it Generated, a test project makes it Test, and otherwise the file's NAMESPACE and PATH words are matched against fixed vocabularies in a fixed ORDER — domain, then infrastructure, then application — so a file whose words hit two layers is counted under the earlier one. A production file matching none of them counts as application, so that share reads 'application or unclassified' rather than a measured application layer. Roles come from naming convention, never from what the code does.
Method: Roslyn line-count by code ROLE: every source file classified Domain/Application/Infrastructure/Test/Generated by namespace + path convention (the shared CodeRoleClassifier), then significant lines summed per role. Deterministic; the advisory score is the business-logic (domain+application) share of production code.
Coverage: Population: ALL source files, each bucketed into ONE of five roles (Domain/Application/Infrastructure/Test/Generated) by namespace + path convention — a file whose layer isn't named in the convention falls to Application (the neutral default), and the split is line-count, not semantic depth or business value.
Other · Architecture — Whether the project-reference graph is acyclic (cycles block independent build/deploy and signal eroding boundaries).
Method: Project reference cycles via elementary-DFS over real .csproj references, using the engine shared with D5/D7; cyclic versus acyclic. Exhaustive, deterministic.
Other · Architecture — Whether dependencies point inward (Domain ← Application ← Infrastructure/Web) — the clean-architecture dependency rule, checked across the project graph.
Method: Layer violations by name-segment inference (Domain/Core to Application to Infrastructure/Web) over the project-reference graph. Exhaustive over all projects, deterministic.
Do you agree with this assessment?
AX8 · Test isolation10.0 / 10Exemplary✓ Tool-verified
Other · Architecture — Whether production projects stay free of references to test projects — tests may depend on production, never the reverse.
Method: Csproj graph: each production project checked for references to test projects (identified by test-framework presence, not name). Zero violations is clean. Deterministic.
Other · Architecture — Whether read (query) handlers stay side-effect-free — a query that writes persistent state or raises events breaks CQS and makes reads unsafe to retry, cache, or route to a read replica.
Method: Roslyn scan: CQRS handlers classified query-vs-command by interface (IQueryHandler/ICommandHandler/IRequestHandler<TQuery,TResult>) and name convention (*Query/Get*/Find* vs *Command); each query handler's body checked for persistent-state writes (SaveChanges/repository Add-Update) or event publishes by resolved invocation. Deterministic, type-level, exhaustive over the detected handlers.
Coverage: Population: CQRS handlers identified by IQueryHandler/ICommandHandler/IRequestHandler interface + *Query/Get*/Find*/*Command NAME convention; query purity then checked exhaustively within that set — a query handler using neither convention is invisible, and mutation is a resolved persistence/publish CALL, not full dataflow.
Other · Domain Modelling — Whether an aggregate references another aggregate by identity rather than embedding it by object reference.
Method: Roslyn (DDD-gated): aggregate roots identified by convention; each aggregate field checked for direct references to other aggregates versus id-only. Deterministic, DDD-native.
Coverage: Population: aggregate roots identified by AggregateRoot/IAggregateRoot base/interface NAME convention; reference-by-identity then checked exhaustively within that set — a root not using those names is invisible.
Other · Domain Modelling — Whether domain identifiers are strongly typed (a newtype wrapper) rather than raw primitives — consistency once an idiom exists.
Method: Roslyn (DDD-gated): strongly-typed id adoption on domain entities/events; raw Guid/int/string ids counted versus wrapped types. An id wrapper is recognised by VALUE SEMANTICS, not by being a struct — a record struct, a record class (`record ApartmentId(Guid Value)`) or a class declared by a typed-id base (`class MemberId : TypedIdValueBase`) all count, while a plain mutable class (reference equality) and a verb-phrase query record (`GetCustomerById`) do not. Deterministic, adoption percentage.
Coverage: Population: id-like members by *Id/*Key NAME suffix; strongly-typed-ID shape then checked semantically — non-suffixed identifiers are not seen.
Do you agree with this assessment?
DM4 · Rich vs anemic domain model7.9 / 10Strong✓ Tool-verified
Other · Domain Modelling — Whether domain entities own their behaviour (invariant-enforcing commands) rather than being data-only structs driven by a foreign service.
Method: Roslyn (DDD-gated): entity method BODIES classified mutator-vs-query — only methods that mutate the entity's own declared state count as invariant-protecting behaviour, so a getter/passthrough doesn't rescue an anemic class. Deterministic, exhaustive over domain-layer entities.
Coverage: Population: entities by name/base convention; rich-vs-anemic judged by classifying each method body mutator-vs-query — logic-bearing domain types outside the convention are invisible.
`BatchManagerMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside. — src/batch/src/monitor/stats.rs:111
`BatchSpillMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside. — src/batch/src/monitor/stats.rs:154
`DistributedQueryMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside. — src/frontend/src/scheduler/distributed/stats.rs:26
`RefreshCycleActors` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside. — src/meta/src/stream/refresh_manager.rs:59
`HummockStateStoreMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside. — src/storage/src/monitor/hummock_state_store_metrics.rs:43
What to do
Move the domain logic onto the entity (invariant-enforcing `&mut self` commands) instead of a foreign service.
Other · Domain Modelling — Whether a domain type's identity-bearing field stays immutable — a `pub` mutable field under a hand-rolled Hash/PartialEq breaks the value-identity invariant.
Method: Roslyn (DDD-gated): entities scanned for publicly writable state — public setters, and (C#/VB) own mutable collections handed out through an auto-property, a public field or a bare-field expression getter, where a computed/copying getter is never charged. One finding per entity; score softened when Marten/EF rehydration frameworks present. Deterministic, framework-aware.
Coverage: Population: entities by convention; encapsulation (setter shape) checked exhaustively within the set.
Other · Domain Modelling — Whether the domain layer stays free of infrastructure dependencies — a domain aggregate fused to a persistence ORM (diesel/sea-orm/sqlx) on its own declaration (active-record) couples the domain to infrastructure. The clean-architecture dependency rule.
Method: Roslyn (DDD-gated): domain-layer types scanned for infrastructure usage in member SIGNATURES and inside method/accessor BODIES — resolved calls and object-creations into EF/Marten/HTTP/Mongo/Redis/message-bus types (not just a namespace allowlist). Deterministic, symbol-resolved, exhaustive over domain-layer bodies, DDD-native.
Coverage: Domain layer identified by NAMESPACE heuristic; infrastructure then resolved by symbol in member SIGNATURES and method/accessor BODIES — rename the layer and the check evaporates.
Other · Domain Modelling — Whether repositories are per aggregate root (not per child entity) and keep the persistence query handle behind the contract, so the root's invariants can't be bypassed.
Method: Roslyn (DDD-gated): repository abstraction detection; repositories over non-aggregate-root entities flagged, and (C#/VB) repository INTERFACES whose members return a live persistence query handle (IQueryable/DbSet/IMongoQueryable) — implementations and specification evaluators are out of population by design, since composing a query internally is what an implementation is for. Deterministic, DDD-native.
Coverage: Population: repositories + aggregate roots by NAME convention; per-root repository rule checked within the set.
`SpringTestRepository` is a repository over `SpringTest`, which is an entity but not an aggregate root. Repositories should be per aggregate ROOT — loading/saving a child entity independently lets callers bypass the root's invariants. Access `SpringTest` through its owning aggregate instead. — integration_tests/client-library/spring-boot/src/main/java/com/risingwave/SpringTestRepository.java:8
What to do
Define repositories per aggregate root and keep the query handle inside them; reach child entities through their root so invariants can't be bypassed.
Other · Event Sourcing — Whether the recovery-replay fold is deterministic — state derived purely from each event's own fields, no clock/random/IO on the replay path.
Method: Roslyn syntax scan (event-sourcing gated): Apply/When folds checked for forbidden tokens (DateTime.Now, Guid.NewGuid, Random, IO), stripped of comments/strings. Deterministic, hard fact per fold.
Other · Event Sourcing — Whether domain events stay immutable (private fields, set once) rather than carrying mutable state.
Method: Roslyn scan (event-sourcing gated): persisted events checked for public setters; immutability verified per property/field. Deterministic, hard fact.
Maturity · Maturity — Whether the repo and its projects have a README, and whether it's substantive and current.
Method: Filesystem scan: README presence, word count, and headings for depth; git history for staleness. Exhaustive across root and project dirs, deterministic.
What to do
Add a build/run (quick start) section to the root README — the first thing a newcomer needs.
Add a 'Testing' section to the root README — how to run the test suite.
Add a README to the 1 of 1 project(s) that lack one — worth up to 2 pts.
Maturity · Maturity — Whether key decisions (ADRs) and the high-level shape (C4/diagrams) are written down.
Method: Filesystem scan: ADR folder/naming conventions or content, plus Mermaid/PlantUML/C4/architecture.md discovery. Exhaustive, deterministic.
No Architecture Decision Records found — no conventional ADR directory, no numbered `NNNN-title` documents in any markup this check reads, and nothing ADR-shaped by content. Design rationale recorded elsewhere (a design-notes tree, a mailing list, pull-request discussion) is not visible to this check and is not re-findable per decision, so a future maintainer cannot ask why one choice was made and get an answer.
What to do
Record significant decisions one document per decision — dated, stating the context, the decision and its consequences — and keep them together wherever your design docs already live (a conventional `docs/adr/` tree, with each file named `NNNN-title` in whatever markup those docs already use, is the most discoverable form).
Maturity · Maturity — Whether the README actually describes the code that exists (LLM-judged, advisory).
Method: Judged by language model at low temperature: README accuracy versus actual projects, within a disclosed tolerance. Advisory, not a measured number.
Only 55/80 runnable modules use logging (modules with no entry point or server are excluded — they are libraries a runnable module hosts). Silent: `.`, `.`, `dashboard`, `develop/sql_bench`, `e2e_test/iceberg` and 20 more.
What to do
Extend structured logging to the remaining runnable modules so everything you run is diagnosable in production.
Add a health-check endpoint (a /health route on your axum/actix router) so orchestrators and load balancers can probe liveness/readiness.
Readiness · Readiness — Whether SAST, secret/dependency scanning and performance benchmarking are wired in (presence, not runtime).
Method: Filesystem scan: SAST configuration, dependency-update automation, secret scanning, and a benchmark harness or benchmark step — in this repository's own ecosystem. Exhaustive, deterministic.
`REDACTED` run(s) a static-analysis scan, but no workflow that runs one is triggered by a pull request (or a merge queue, or an unfiltered push) — the scan fires on a schedule or a manual dispatch only. A vulnerable change therefore merges clean and is reported on the next scheduled run, by which time it is on the default branch and the only remedy is a follow-up fix. Add the pull-request trigger to the workflow that runs the scan so the finding arrives before the merge rather than after it.
What to do
Trigger your SAST workflow on pull requests — a scan that only runs on a cron reports history, it does not gate.
Dependabot is configured but does not watch `nuget`, `npm`, `gomod`, `pip` — add those `package-ecosystem` entries to REDACTED so those dependencies get the same automatic update and advisory pressure as the ones it already covers.
Add gitleaks/trufflehog in CI to block PRs that introduce committed secrets.
Readiness · Readiness — Whether releases are automated and safely reversible (probes, rolling updates, approval gates) — from manifests/pipeline files, not the live environment.
Method: Filesystem scan: deployment manifests/IaC (K8s YAML, Helm, Terraform) for rolling updates, probes, approval gates, migration hooks. Exhaustive, deterministic.
Do you agree with this assessment?
P5 · DR & Backup7.0 / 10Strong✓ Tool-verified
Readiness · Readiness — Whether disaster recovery is planned and codified — backups, geo-recovery, RTO/RPO, persistence guarantees — from IaC + container manifests + docs, never the live cloud.
Method: Filesystem scan: disaster recovery, backup, geo-recovery, RTO/RPO, persistence guarantees from IaC, manifests, and docs. Exhaustive, deterministic, never a live environment.
What to do
Document RTO/RPO and a tested restore procedure (a backup config alone isn't disaster recovery).
Readiness · Readiness — Whether outbound HTTP calls are wrapped in resilience (retry/timeout/circuit-breaker) so a failing dependency doesn't cascade.
Method: Source scan: outbound HTTP clients and what bounds them — resilience handlers (Polly, AddStandardResilienceHandler) on .NET; on Go, the JVM, Python, JavaScript/TypeScript, Ruby, PHP, Rust, Elixir, Swift, Dart and Erlang, a timeout, deadline, retry or breaker beside each call, or a process-wide client default (a framework-wide deadline such as Drupal core's, Laravel's or actix's awc counts). Exhaustive, deterministic.
`fetch(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout. 14 of the 19 files that make outbound calls are unbounded; the first 10 are listed. — dashboard/lib/api/api.ts:48
`RestClient.builder(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout. (×2) — java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/ElasticRestHighLevelClientAdapter.java:61, java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/OpensearchRestHighLevelClientAdapter.java:58
`Client::builder()` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout. — src/common/secret/src/vault_client.rs:170
`reqwest::get(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout. (×3) — src/common/src/telemetry/mod.rs:180, src/connector/codec/src/decoder/json/mod.rs:133, src/connector/src/parser/utils.rs:70
`reqwest::Client::new(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout. — src/common/telemetry_event/src/util.rs:32
`reqwest::Client::builder(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout. (×2) — src/connector/src/sink/doris.rs:493, src/connector/src/sink/http.rs:310
What to do
Bound every outbound call: pass `signal: AbortSignal.timeout(ms)` to `fetch`, set `timeout` on the axios instance (`axios.create({ timeout })`), and add retries with back-off (`axios-retry`, `p-retry`) and a breaker (`opossum`, `cockatiel`) around dependencies that fail.
Set connect and read timeouts on every client (`RestTemplateBuilder.connectTimeout/readTimeout`, WebClient `responseTimeout`, `HttpRequest.Builder.timeout`, `HttpURLConnection.setReadTimeout`, Feign `connectTimeout`/`readTimeout` in configuration), and wrap calls to dependencies in resilience4j `@Retry`/`@CircuitBreaker`/`@TimeLimiter` (or Spring Retry).
Give every client a whole-request bound: `reqwest::Client::builder().timeout(Duration::from_secs(10))` (never `reqwest::get` or `Client::new()`, which have none), ureq's `timeout_global`, or wrap the call in `tokio::time::timeout`; add retry with back-off (`reqwest-retry`'s `RetryTransientMiddleware`, `backoff`) around dependencies that fail.
Readiness · Performance — Whether asynchronous code stays responsive — it avoids sync-over-async blocking (a .NET .Wait()/.GetAwaiter().GetResult(), a time.sleep or blocking HTTP call inside a Python coroutine, a *Sync call inside an async JavaScript function, block_on inside a Rust async fn, runBlocking inside a Kotlin suspend function, block() inside a Reactor publisher) that stalls a thread or event loop and risks deadlock, and, where the code is a reusable library on .NET, awaits with ConfigureAwait(false) so it never captures and stalls its caller's context.
Method: Production-source scan: sync-over-async blocking counted everywhere — .Wait()/.GetAwaiter().GetResult() in .NET; off .NET, read from the language model, a blocking call inside an async function (Python, TS/JS, Rust, Kotlin) or inside a Java method returning a Reactor Mono/Flux — and, for a .NET library with ≥5 awaits, the share of awaits using ConfigureAwait(false). Deterministic, syntax/text detection.
Do you agree with this assessment?
R1 · Type Safety8.2 / 10Strong✓ Tool-verified
React / JS · Code Health — How much of the frontend is typed TypeScript vs untyped JavaScript.
Method: Frontend file inventory: the share of typed TypeScript vs untyped JavaScript across the source tree. Deterministic, exhaustive over frontend files.
What to do
Migrate the remaining .js/.jsx files to TypeScript.
React / JS · Code Health — Near-exact copy-pasted blocks of substantial extent across the frontend (the D4 clone algorithm over JS/TS tokens, D-386): a block is reported only where its copies still agree on most of their own identifiers and literals, or were renamed as they were pasted but kept most of their constants, and where the copies carry enough code to stand on their own or the copied extent reaches 30 lines — so a re-implementation sharing neither names nor values, and a small pasted declaration, are both found and deliberately not reported, and a clean R10 is not a claim that nothing was copied.
Method: Near-exact copy-pasted blocks of substantial extent across the frontend (the D4 clone algorithm run over JS/TS tokens). Masking finds the candidates; a block is reported when its copies still agree on most of their own identifiers and literals, or when a renamed copy still agrees on most of its constants, AND the copies carry enough code to stand on their own — or when the copied extent reaches 30 lines. So a re-implementation sharing neither names nor values, and a small pasted declaration, are deliberately not counted. Deterministic.
dashboard/pages/cpu_profiling.tsx:41 · dashboard/pages/heap_profiling.tsx:48 — the two spans are one implementation copied and then locally edited — 621 tokens are still identical, in the same order in both files, with only local edits between them. The copies have already begun to drift, which is this row's finding: an edit made to one and not the other changes behaviour silently. Diff the two spans first to learn what genuinely differs, then extract the shared core into one module both sites use, passing the differences in as parameters — or, if one copy exists only because the other could not be imported from its context, make one of them the single source the other is generated or re-exported from. If one copy is no longer reachable, delete it rather than letting it shadow the live one. — dashboard/pages/cpu_profiling.tsx:41
dashboard/pages/fragment_graph.tsx:337 · dashboard/pages/relation_graph.tsx:93 — the two spans are one implementation copied and then locally edited — 329 tokens are still identical, in the same order in both files, with only local edits between them. The copies have already begun to drift, which is this row's finding: an edit made to one and not the other changes behaviour silently. Diff the two spans first to learn what genuinely differs, then extract the shared core into one module both sites use, passing the differences in as parameters — or, if one copy exists only because the other could not be imported from its context, make one of them the single source the other is generated or re-exported from. If one copy is no longer reachable, delete it rather than letting it shadow the live one. — dashboard/pages/fragment_graph.tsx:337
dashboard/pages/await_tree.tsx:133 · dashboard/pages/heap_profiling.tsx:277 — the 2 copies are spread across 2 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/pages/await_tree.tsx:133
dashboard/components/FragmentGraph.tsx:529 · dashboard/components/RelationGraph.tsx:221 — the 2 copies sit in sibling files in one directory, so check first whether one of them (or an existing module there) already owns this behaviour and the others should call it; otherwise extract it into one module in that directory and have each site call it. — dashboard/components/FragmentGraph.tsx:529
dashboard/components/FragmentGraph.tsx:328 · dashboard/components/FragmentGraph.tsx:533 · dashboard/components/RelationGraph.tsx:223 · dashboard/components/RelationGraph.tsx:380 — the 2 copies sit in sibling files in one directory, so check first whether one of them (or an existing module there) already owns this behaviour and the others should call it; otherwise extract it into one module in that directory and have each site call it. — dashboard/components/FragmentGraph.tsx:328
dashboard/lib/api/streamingStats.ts:83 · dashboard/lib/api/streamingStats.ts:118 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. — dashboard/lib/api/streamingStats.ts:83
dashboard/components/utils/stroke-icons.tsx:124 · dashboard/components/utils/stroke-icons.tsx:233 — all 2 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/components/utils/stroke-icons.tsx:124
dashboard/pages/cluster.tsx:293 · dashboard/pages/cluster.tsx:309 — all 2 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/pages/cluster.tsx:293
dashboard/lib/algo.ts:31 · dashboard/lib/algo.ts:52 — the two spans are one implementation copied and then locally edited — 63 tokens are still identical, in the same order in both spans, with only local edits between them. The copies have already begun to drift, which is this row's finding: an edit made to one and not the other changes behaviour silently. Diff the two spans first to learn what genuinely differs, then extract the shared core into one module both sites use, passing the differences in as parameters — or, if one copy exists only because the other could not be imported from its context, make one of them the single source the other is generated or re-exported from. If one copy is no longer reachable, delete it rather than letting it shadow the live one. — dashboard/lib/algo.ts:31
dashboard/components/FragmentGraph.tsx:246 · dashboard/components/FragmentGraph.tsx:262 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. — dashboard/components/FragmentGraph.tsx:246
dashboard/pages/await_tree.tsx:103 · dashboard/pages/fragment_graph.tsx:372 · dashboard/pages/heap_profiling.tsx:204 — the 3 copies are spread across 3 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/pages/await_tree.tsx:103
dashboard/components/FragmentDependencyGraph.tsx:159 · dashboard/components/FragmentDependencyGraph.tsx:171 — all 2 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/components/FragmentDependencyGraph.tsx:159
dashboard/components/FragmentGraph.tsx:188 · dashboard/components/RelationGraph.tsx:127 — the 2 copies are spread across 2 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/components/FragmentGraph.tsx:188
dashboard/components/FragmentGraph.tsx:148 · dashboard/components/RelationGraph.tsx:92 — the 2 copies sit in sibling files in one directory, so check first whether one of them (or an existing module there) already owns this behaviour and the others should call it; otherwise extract it into one module in that directory and have each site call it. — dashboard/components/FragmentGraph.tsx:148
dashboard/components/utils/backPressure.tsx:19 · dashboard/components/utils/backPressure.tsx:73 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. — dashboard/components/utils/backPressure.tsx:19
dashboard/components/FragmentGraph.tsx:509 · dashboard/components/RelationGraph.tsx:203 — the 2 copies are spread across 2 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/components/FragmentGraph.tsx:509
dashboard/pages/fragment_graph.tsx:403 · dashboard/pages/fragment_graph.tsx:414 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. — dashboard/pages/fragment_graph.tsx:403
dashboard/pages/await_tree.tsx:71 · dashboard/pages/await_tree.tsx:80 · dashboard/pages/await_tree.tsx:88 — all 3 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported. — dashboard/pages/await_tree.tsx:71
dashboard/pages/fragment_graph.tsx:454 · dashboard/pages/fragment_graph.tsx:462 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. — dashboard/pages/fragment_graph.tsx:454
What to do
Act on each finding's own remediation rather than one rule: the move depends on what recurs. Where the copies are executable blocks, give the shared part one home and call it from each site; where they are declarations, a listing, a specialisation already delegating to its base, or one shape repeated per entity, there is no call site and the move is a shared type, a generated set or a factory — sometimes there is nothing to extract.
React / JS · Code Health — Per-function cyclomatic/cognitive complexity from the token-level function scanner (D-386) — real branching, not a regex heuristic.
Method: Per-function cyclomatic/cognitive complexity from a token-level function scanner (real branching, not a regex heuristic), computed over every frontend function. Deterministic.
Do you agree with this assessment?
R3 · Large Files7.7 / 10Strong✓ Tool-verified
React / JS · Code Health — How many source files exceed the large-file threshold.
Method: Components/modules exceeding the large-file threshold, counted exhaustively across the frontend source tree. Deterministic.
What to do
Split each oversized file along the responsibilities already in it, into smaller focused modules in the same package.
Do you agree with this assessment?
R6 · Tooling10.0 / 10Exemplary✓ Tool-verified
React / JS · Readiness — Whether the project wires up test, lint and typecheck — detected from each package.json script's COMMAND (eslint / tsc / vitest / jest / playwright), not just its name, and corroborated against CI-workflow invocations so a tool run only in CI still counts.
Method: package.json scanned for test/lint/typecheck script wiring. Deterministic presence check.
Do you agree with this assessment?
R7 · Dead Code9.9 / 10Exemplary✓ Tool-verified
React / JS · Code Health — Files unreachable from every application/tooling/test entry point, and exports nothing imports (module-graph reachability, D-386).
Method: Dead code: files unreachable from every application/tooling/test entry point plus exports nothing imports, via module-graph reachability. Deterministic, exhaustive over the import graph.
4 file(s) (~199 LoC) were excluded from dead-code analysis — declare main/module/exports or a conventional entry (src/index.*, an index.html script) so reachability can see this package.
50 file(s) (~6860 LoC) were excluded from dead-code analysis. This package's entry point(s) resolved, but the walk stopped one hop in: dashboard/pages/await_tree.tsx imports '../proto/gen/monitor_service', which is not in the scanned tree. That is usually a generated or build-output module, so reachability cannot see past it and no dead-code claim is made about this package. Nothing is necessarily wrong here. — dashboard
2 file(s) (~54 LoC) were excluded from dead-code analysis — declare main/module/exports or a conventional entry (src/index.*, an index.html script) so reachability can see this package. — src/utils/pgwire/tests/js
Nothing imports this binding — it is safe to review for removal. — dashboard/lib/utils/timeUtils.ts:106
React / JS · Readiness — npm dependency truthfulness (D-386): unused dependencies, imports not declared anywhere, and type-/test-only packages shipped as production deps.
Method: npm dependency truthfulness: unused dependencies, imports declared nowhere, and type-/test-only packages shipped as production deps — from the manifest + import graph. Deterministic.
Declared in dashboard/package.json but never imported anywhere in that package or its workspace members — no static import reaches it. Usually that is dead weight and attack surface, but two shapes are indistinguishable from source and are NOT dead: an optional or native peer that another dependency loads dynamically at runtime, and a package a build, docs or test step installs and invokes separately. Confirm which of the three this is before removing it. (×3)
What to do
Remove unused dependencies, declare unlisted imports explicitly, and demote type-/test-only packages to devDependencies.
React / JS · Architecture — Import cycles in the module graph (D-386) — files that can only be understood and changed together.
Method: Import cycles in the module graph, detected exhaustively over JS/TS imports (the same cycle detection as the .NET coupling dimension). Deterministic.
Other · Security — Only what this repository's own non-C# files could be read for was assessed — and because this repository commits the configuration that serves its own HTTP surface, that configuration could be read in full for the security response headers it sets. Nothing else in this dimension was assessed: the transport, cookie, input-validation and crypto controls are read from a source model that was not loaded for this repository’s language, so their absence here is not a finding about this repository.
No Content-Security-Policy / X-Frame-Options / X-Content-Type-Options configuration found — defense in depth, even when a reverse proxy could set them. This is reported because `REDACTED` builds the web-server image that serves this application, so the configuration that would carry these headers is in this repository and was read in full. (−2.0 on this card.) — integration_tests/iceberg-sink/Dockerfile:1
What to do
Set security response headers on the surface this repository serves: an `add_header` directive per header in the nginx/Caddy/Apache config, a `_headers` / `vercel.json` / `netlify.toml` entry for a static host, or `helmet()` in the HTTP server. `Content-Security-Policy` is the one that pays for itself first — it is what contains an injected script once one reaches the page — followed by `X-Content-Type-Options: nosniff` and a frame policy (`X-Frame-Options: DENY`, or CSP `frame-ancestors`). Where the app is served from a build container, the header configuration belongs in the image beside the built assets, so it ships with them rather than depending on where it lands.
Do you agree with this assessment?
WCAG coverage — what static analysis assessed
Statically assessed 10 of 55 WCAG 2.2 Level A/AA success criteria (18%; ≈20% of the 50 WCAG 2.1 AA criteria for EN 301 549). The other 45 require runtime or manual evaluation. Partial signal only (a clean result is necessary, not sufficient; static analysis fully verifies none). This is accessibility readiness, not a conformance claim — a WCAG conformance claim requires manual evaluation (WCAG-EM 1.0).
The score is the rank-weighted fold of these lenses (worst-heaviest), each including its meta-dimensions; a lens with a Critical contributor is capped at Fair (its band reads "gated by …") and is never the strongest area however high its average.
Unscored — 1 check(s) recorded observations but carry no score
These checks ran and found something, but they do not carry a score — either by design (an advisory check reports evidence rather than grading it) or because they could not be scored here. They are excluded from the score for that reason, not because there was nothing to see.
SC1 Supply-chain hygiene — 1 observation(s) recorded · Advisory — this card reports evidence and never carries a score, so there is nothing missing here.
Not evidenced — 3 control(s) we could not find positive evidence for
These checks grade a working control, and the repository shows no evidence of one. That is deliberately not scored as a zero: a repository cannot show an ops runbook, a database TTL or an infrastructure-side audit log, so absence of evidence here is not evidence the control is missing. It is also not a statement that the check is irrelevant to this codebase — the thing it grades applies; we just could not see it. Excluded from the score either way.
C3 Audit Trail — Not assessed: these audit controls are read from a source model (declarative annotations, request middleware, entity/column names, guard methods) that was not loaded for this repository — because the repository is written in a language this check does not yet model, or because its projects failed to load. Absence of an idiom this check recognises is NOT evidence that this repository lacks audit controls: it may implement them entirely in its own ecosystem. This is a gap in the analyzer's language coverage, not a finding about this repository.
C4 Data Retention — Not assessed: these retention controls are read from a source model (declarative annotations, request middleware, entity/column names, guard methods) that was not loaded for this repository — because the repository is written in a language this check does not yet model, or because its projects failed to load. Absence of an idiom this check recognises is NOT evidence that this repository lacks retention controls: it may implement them entirely in its own ecosystem. This is a gap in the analyzer's language coverage, not a finding about this repository.
C5 Data-Subject Rights — Not assessed: these data-subject rights controls are read from a source model (declarative annotations, request middleware, entity/column names, guard methods) that was not loaded for this repository — because the repository is written in a language this check does not yet model, or because its projects failed to load. Absence of an idiom this check recognises is NOT evidence that this repository lacks data-subject rights controls: it may implement them entirely in its own ecosystem. This is a gap in the analyzer's language coverage, not a finding about this repository.
Not included — 64 check(s) not relevant to this codebase
These checks had nothing to measure here (no tests, no git history, the codebase is small, or the architecture style doesn't apply), so they're omitted above rather than scored low.
AC1 Text alternatives — No image/media element found in the parsed markup — AC1 not applicable here.
AC4 Keyboard semantics — No interactive element found in the parsed markup — AC4 not applicable here.
AX1 Captive dependencies — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
AX2 Stateful singletons — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
AX5 Architecture & structure — not assessed — architecture style/structure is computed from a project graph (projects, types, module namespaces) that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
AX6 Interface segregation — not assessed — interface segregation is computed over a type surface that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
AX7 Slice cohesion — not applicable — not a vertical-slice architecture
AXB2 Runtime readiness — Advisory — this card reports evidence and never carries a score, so there is nothing missing here.
AXR1 Runtime accessibility — compose up failed (exit 18 — an image could not be pulled) — sink-mongodb-test-env Error context canceled sink-common-test-env Error context canceled source-cdc-test-env Error context canceled sink-kafka-test-env Error context canceled db Error context canceled mongodb-mtls-setup Error context canceled sink-mqtt-test-env Error context canceled elasticsearch Error context canceled Error response from daemon: Get "https://registry-1.docker.io/v2/": Forbidden; the earlier `compose pull` step reported: moto Pulling moto Error context canceled elasticsearch Error context canceled db Error context canceled sink-postgres-test-env Error context canceled sqlserver-server Error context canceled pubsub-emulator Error context canceled release-env-x86 Error context canceled release-env-arm Error context canceled Error response from daemon: Get "https://registry-1.docker.io/v2/": Forbidden; the runtime sandbox reaches registries only through the in-fence pull-through mirror, so an image the mirror does not carry cannot be fetched — this is a limit of our sandbox, not of your stack; runtime evidence skipped This is a statement about this run, not a statement about your application: nothing here says the surface is inaccessible, only that it was never rendered.
C1 Data Protection — Not assessed: these personal data controls are read from a source model (declarative annotations, request middleware, entity/column names, guard methods) that was not loaded for this repository — because the repository is written in a language this check does not yet model, or because its projects failed to load. Absence of an idiom this check recognises is NOT evidence that this repository lacks personal data controls: it may implement them entirely in its own ecosystem. This is a gap in the analyzer's language coverage, not a finding about this repository.
C2 Access Controls — Not assessed: these authorization controls are read from a source model (declarative annotations, request middleware, entity/column names, guard methods) that was not loaded for this repository — because the repository is written in a language this check does not yet model, or because its projects failed to load. Absence of an idiom this check recognises is NOT evidence that this repository lacks authorization controls: it may implement them entirely in its own ecosystem. This is a gap in the analyzer's language coverage, not a finding about this repository.
D11 Test Reliability — Test reliability not scored — polyglot repository, one half has no runner
D18 Solution Shape — D18 scores the shape of a .NET solution, but this repository's production source is mostly .go, .java, .php, .py, .rb, .rs, .ts, .tsx — the .NET project files present are an immaterial minority — so the dimension does not apply.
D20 ADR Quality — N/A — ADRs are expected on deployable products with a user-facing host, not consumed libraries; no ADR log is required here.
D23 Boundary Type-Coupling — At only 773399 LoC across 1 project there is no size or structure to justify any boundaries. Aggregate roots WERE found in 2 sibling source directories (core, impl), but bounded contexts are resolved over the loaded C#/VB project set, which named fewer than two — so there was nothing to measure coupling across. Declaring this codebase's bounded contexts (≥2) resolves them directly. Declare them in `.codehealth/config.yaml` at the repository root (create it if absent), mapping each context name to the module-path or namespace prefixes that belong to it — e.g. `architecture:` → `contexts:` → `Billing: ["src/billing", "Acme.Billing"]`, `Catalog: ["src/catalog", "Acme.Catalog"]`.
D25 ADR Conformance — no ADRs to check
D27 Navigability — symbol resolution incomplete — too few calls resolved to assess navigability
D32 Data Compliance (PII/GDPR) — No personal data was found crossing a boundary the PII/GDPR ruleset checks — nothing written to a log or console sink, placed in a URL or query string, or persisted to browser storage. That is a clean result for the LEAK surface only: this ruleset detects personal data escaping, it does not inventory the personal data a repository holds, so it is not evidence that this repository has no personal-data surface. The personal-data map (Appendix C) and the C1-C5 compliance cards are what speak to that.
D39 IL Efficiency — IL not measured — the analyzer's build of the target did not succeed
D40 Network Egress Confinement — No Kubernetes/orchestration workloads found in the repository manifests; network egress policy is a cluster-native control that may live at the platform/firewall layer, so there is nothing to assess here.
D41 Kernel & Syscall Confinement — No Kubernetes/orchestration workloads found in the repository manifests; seccomp/AppArmor/SELinux confinement is a workload-level control, so there is nothing to assess here.
D42 Runtime Threat Enforcement — No Kubernetes/orchestration workloads found in the repository manifests; runtime threat-detection and admission-control policy are cluster-level controls, so there is nothing to assess here.
D6 Cohesion (LCOM4) — D6 reads a CS/VB/GO/SCALA/SWIFT/DART/JAVA/PY/KT/TS/TSX/MTS/CTS/JS/JSX/MJS/CJS/PHP class graph only — this repository's production source is .rb, .rs, which was left unread. Not scored: this is a gap in the analyzer, not a verdict about this repository.
D7 Architectural Integrity — no checkable ADRs and no dependency cycles — architectural integrity not assessed
D8 Code Coverage — Coverage NOT MEASURED: the .NET half could not be measured — no coverage produced (collector absent, or test run exceeded the inline budget); the JavaScript/TypeScript half could not be measured — the jest suite in src/utils/pgwire/tests/js/ ran and not one test passed (FAIL test/pgwire.test.ts), so the coverage would describe the failed run, not the code. This repository's production source spans both ecosystems, and no partial figure is published as if it were the whole: coverage is excluded from the score rather than counted as a near-zero. The named suite step is one the repository's maintainers can perform; once it passes, the real number is measured on the next scan. Alternatively, commit the lcov/Cobertura report your CI produces and it is read without a re-run.
DM3 Integration-event coupling — no integration events detected — coupling check not applicable
ED2 Event/command shape — not scored — deciding whether a command has more than one competing handler requires resolving the call graph, and a call made through an inferred or generic receiver has no resolvable owner in the source. Reported as guidance rather than measured
ED5 Idempotency — This check finds retry-prone mutations (command handlers and message/event consumers) by walking the repository's declared types, and none was loaded here, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
GD1 Unfinished & placeholder code — no source files were read — this check reads C# syntax, and none was loaded for this repository. That is a limit of the analyzer, not a finding about your code.
IC1 Incompleteness & stubs — reported, not scored — this repository's C# declares no analysable method bodies (a constants, record or DTO assembly), and this score is a density of unfinished work per method, which has no denominator here. The file-level signals below were still collected and are shown in full
P12 CI test-gate honesty — Reported, not scored — this card publishes what the CI gate does with the test inventory rather than grading it. The findings above are its output.
P8 Schema migrations — Hibernate, SQLAlchemy, SeaORM, sqlx is declared, but the schema-migration mechanism could not be identified. Our limit, not a verdict on this repository.
P9 Domain vs controller coverage — no coverage report found on disk — produce a coverage report in a standard format (lcov — `cargo install cargo-llvm-cov`, then `cargo llvm-cov --lcov --output-path lcov.info`) and commit it — a hosted scan measures a clone of the repository, so a report that exists only in a working tree, a CI runner's or your own, never reaches it; the artefact is commonly gitignored, so `git add -f` that one file (or un-ignore its path) and commit it alongside the code it measures, or wire coverage collection into CI, to enable this cross-layer check
PF1 Benchmark discipline — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
PF2 Allocation hygiene — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
R11 Import Boundaries — No recognizable feature-sliced/layered src layout — boundary rules not applicable.
R4 Test Coverage — 9 test file(s) reach none of 47 production file(s) via imports — exercised outside the JS import graph (integration/bundled), not import-reachable
R5 Dependency Freshness — uses a pnpm lockfile — dependency freshness not measured here; JS/npm CVEs are scored in D30 (Dependency Vulnerabilities), which answers every ecosystem
X1 Async correctness — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
X12 Unreachable branch — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X13 Undrained process stream — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X14 Bypassable address classification — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X15 Unvalidated length from an untrusted reader — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X16 Unfloored truncation loop — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X17 Uncapped recursion over a caller-supplied document — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X18 Disposal-pattern correctness — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X19 Unrestored process-global state — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X2 Cancellation propagation — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
X20 Mistyped argument guard — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X21 Side-effecting pattern guard — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X22 Contradicted release guard — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X23 Unguarded diagnostic materialisation — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X24 Document value interpolated into markup unescaped — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X25 Inert configuration knob — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X26 Unsynchronised callback handoff — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X27 Collection changed while being enumerated — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X28 Index access outside its own emptiness guard — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X29 Per-element action decided by a fixed element — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X3 Exception handling — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
X30 Support guard that admits what it rejects — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X32 Type resolved by simple name across every loaded assembly — This check reads C# syntax; no C# was loaded for this repository, so it has nothing to report. That is a limit of the analyzer, not a finding about your code.
X4 Structured logging — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
X5 Nullable reference types — not analysed — these correctness checks read a source model that was not loaded for this repository, because the repository is written in a language this check does not yet model, or because its projects failed to load. This is a gap in the analyzer, not a finding about this repository
X9 Subsumed condition operand — Advisory — this card reports evidence and never carries a score, so there is nothing missing here.
Appendix A — Findings (grouped)
The findings behind the scores, grouped by severity, then by dimension and kind. The high-severity issues are enumerated in full below; items per group are capped at 25 with any overflow stated explicitly per group, never silently truncated. The complete machine-readable list of every finding (all severities) is the companion findings.md in this report's bundle.
Boundary-crossing change coupling: pure.rs ↔ strong.rs src/frontend/src/expr/pure.rs— `src/frontend/src/expr/pure.rs` (context expr) and `src/frontend/src/optimizer/plan_expr_visitor/strong.rs` (context optimizer) sit in DIFFERENT parts of the tree yet change together 93% of the time (43 of the 46 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 43 shared commits counted here, the most recent 3 are `6e8b2689` feat(expr): support volatile timestamp and uuid functions (#26362); `4339a18e` feat(expr): support array overlap predicates (#25597); `55bf4572` feat(expr): implement crc32 and crc32c bytea functions (#24964) — run `git show` on any of them.
Boundary-crossing change coupling: mock_hummock_meta_client.rs ↔ hummock_meta_client.rs src/meta/src/hummock/mock_hummock_meta_client.rs— `src/meta/src/hummock/mock_hummock_meta_client.rs` (context meta) and `src/storage/src/hummock/hummock_meta_client.rs` (context storage) sit in DIFFERENT parts of the tree yet change together 93% of the time (14 of the 15 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 14 shared commits counted here, the most recent 3 are `68694f40` feat(compaction): support manual compact target level (#25765); `78494334` refactor(meta): improve the determinism of trigger_manual_compaction …; `1611e1bf` feat(proto): introduce iceberg compaction proto (#21778) — run `git show` on any of them.
Boundary-crossing change coupling: lib.rs ↔ meta_client.rs src/meta/service/src/lib.rs— `src/meta/service/src/lib.rs` (context meta) and `src/rpc_client/src/meta_client.rs` (context rpc_client) sit in DIFFERENT parts of the tree yet change together 83% of the time (10 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 10 shared commits counted here, the most recent 3 are `f2d2606b` refactor: deduplicate await-tree fetching & add registry for meta nod…; `1611e1bf` feat(proto): introduce iceberg compaction proto (#21778); `5bb02eae` feat(iceberg): support iceberg jdbc catalog views (#21400) — run `git show` on any of them.
Boundary-crossing change coupling: SinkWriterStreamObserver.java ↔ remote.rs java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/SinkWriterStreamObserver.java— `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/SinkWriterStreamObserver.java` (context java) and `src/connector/src/sink/remote.rs` (context connector) sit in DIFFERENT parts of the tree yet change together 83% of the time (10 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 10 shared commits counted here, the most recent 3 are `001ac816` fix: change JNI sink normal logs to debug level (#19758); `ff495144` fix: deprecate `SinkPayloadFormat` (#16723); `f47a892e` feat(sink): support es sink struct and refactor es sink (#14231) — run `git show` on any of them.
Boundary-crossing change coupling: risingwave-dev-dashboard.dashboard.py ↔ compactor_metrics.rs grafana/risingwave-dev-dashboard.dashboard.py— `grafana/risingwave-dev-dashboard.dashboard.py` (context grafana) and `src/storage/src/monitor/compactor_metrics.rs` (context storage) sit in DIFFERENT parts of the tree yet change together 79% of the time (11 of the 14 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 11 shared commits counted here, the most recent 3 are `92f70db9` feat(storage): support block_size metrics (#17660); `035da38d` feat(storage): Improve task measurement on the compactor side with pa…; `3e976cc3` chore(metric): fix table id filter and some panel reorgs (#12148) — run `git show` on any of them.
Boundary-crossing change coupling: builtin_scalar.rs ↔ pure.rs src/frontend/src/binder/expr/function/builtin_scalar.rs— `src/frontend/src/binder/expr/function/builtin_scalar.rs` (context binder) and `src/frontend/src/expr/pure.rs` (context expr) sit in DIFFERENT parts of the tree yet change together 78% of the time (28 of the 36 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 28 shared commits counted here, the most recent 3 are `6e8b2689` feat(expr): support volatile timestamp and uuid functions (#26362); `4339a18e` feat(expr): support array overlap predicates (#25597); `55bf4572` feat(expr): implement crc32 and crc32c bytea functions (#24964) — run `git show` on any of them.
Boundary-crossing change coupling: builtin_scalar.rs ↔ strong.rs src/frontend/src/binder/expr/function/builtin_scalar.rs— `src/frontend/src/binder/expr/function/builtin_scalar.rs` (context binder) and `src/frontend/src/optimizer/plan_expr_visitor/strong.rs` (context optimizer) sit in DIFFERENT parts of the tree yet change together 78% of the time (28 of the 36 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 28 shared commits counted here, the most recent 3 are `6e8b2689` feat(expr): support volatile timestamp and uuid functions (#26362); `4339a18e` feat(expr): support array overlap predicates (#25597); `55bf4572` feat(expr): implement crc32 and crc32c bytea functions (#24964) — run `git show` on any of them.
Boundary-crossing change coupling: Binding.java ↔ macros.rs java/java-binding/src/main/java/com/risingwave/java/binding/Binding.java— `java/java-binding/src/main/java/com/risingwave/java/binding/Binding.java` (context java) and `src/jni_core/src/macros.rs` (context jni_core) sit in DIFFERENT parts of the tree yet change together 78% of the time (14 of the 18 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 14 shared commits counted here, the most recent 3 are `aace224a` fix(cdc): share type compatibility validation for schema changes (#26…; `d21c9335` fix(mysql-cdc): introduce `OpendalSchemaHistory` to resolve the schem…; `54711c25` refactor(connector): correctly log java exceptions (#20840) — run `git show` on any of them.
Boundary-crossing change coupling: catalog_service.rs ↔ ddl_controller.rs src/frontend/src/catalog/catalog_service.rs— `src/frontend/src/catalog/catalog_service.rs` (context catalog) and `src/meta/src/rpc/ddl_controller.rs` (context meta) sit in DIFFERENT parts of the tree yet change together 77% of the time (36 of the 47 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 36 shared commits counted here, the most recent 3 are `b927f6c8` feat(ddl): support resource group alter for databases, sinks and inde…; `fa7a8840` feat(meta): support wait jobs (#25133); `b5e216c4` feat: enable clippy lints for stack overflow detection & fix warnings… — run `git show` on any of them.
Boundary-crossing change coupling: opts.rs ↔ state_table.rs src/storage/hummock_trace/src/opts.rs— `src/storage/hummock_trace/src/opts.rs` (context storage) and `src/stream/src/common/table/state_table.rs` (context stream) sit in DIFFERENT parts of the tree yet change together 75% of the time (12 of the 16 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 12 shared commits counted here, the most recent 3 are `f6628e44` feat(observability): add fragment-level immutable memtable memory met…; `11222b5d` feat(storage): support state clean for watermark in either pk or valu…; `053e1e61` feat(storage): batch add flushed imm to uploader (#22342) — run `git show` on any of them.
Boundary-crossing change coupling: rw_fragments.rs ↔ stream_service.rs src/frontend/src/catalog/system_catalog/rw_catalog/rw_fragments.rs— `src/frontend/src/catalog/system_catalog/rw_catalog/rw_fragments.rs` (context catalog) and `src/meta/service/src/stream_service.rs` (context meta) sit in DIFFERENT parts of the tree yet change together 73% of the time (8 of the 11 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `914f962d` perf: avoid fetching stream nodes in system catalogs (#24641); `3512bee3` feat: expose parallelism_policy in fragment metadata and system catal…; `aa180c40` feat(meta): let stream actors in fragment share same stream node (#20… — run `git show` on any of them.
Boundary-crossing change coupling: vnode_placement.rs ↔ scale.rs src/common/src/vnode_mapping/vnode_placement.rs— `src/common/src/vnode_mapping/vnode_placement.rs` (context common) and `src/meta/src/stream/scale.rs` (context meta) sit in DIFFERENT parts of the tree yet change together 73% of the time (8 of the 11 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `709894d8` fix: Fix the panic issue with the parallelism() call (#19849); `9bc0b1fb` feat: introduce node label (#19153); `8d5b62b1` feat: variable vnode count support in batch/streaming scheduler (#18407) — run `git show` on any of them.
Boundary-crossing change coupling: hummock_service.rs ↔ hummock_meta_client.rs src/meta/service/src/hummock_service.rs— `src/meta/service/src/hummock_service.rs` (context meta) and `src/rpc_client/src/hummock_meta_client.rs` (context rpc_client) sit in DIFFERENT parts of the tree yet change together 71% of the time (10 of the 14 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 10 shared commits counted here, the most recent 3 are `68694f40` feat(compaction): support manual compact target level (#25765); `78494334` refactor(meta): improve the determinism of trigger_manual_compaction …; `1611e1bf` feat(proto): introduce iceberg compaction proto (#21778) — run `git show` on any of them.
Boundary-crossing change coupling: cluster_service.rs ↔ meta_client.rs src/meta/service/src/cluster_service.rs— `src/meta/service/src/cluster_service.rs` (context meta) and `src/rpc_client/src/meta_client.rs` (context rpc_client) sit in DIFFERENT parts of the tree yet change together 71% of the time (12 of the 17 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 12 shared commits counted here, the most recent 3 are `4afdad11` fix(batch): mask serving workers with version mismatch (#26559); `086b9030` refactor(meta): deprecate is_unschedulable for worker (#25003); `200ed05c` feat(meta): add a rpc to fetch meta store endpoint (#19594) — run `git show` on any of them.
Boundary-crossing change coupling: function_catalog.rs ↔ REDACTED src/frontend/src/catalog/function_catalog.rs— `src/frontend/src/catalog/function_catalog.rs` (context catalog) and `src/meta/src/controller/mod.rs` (context meta) sit in DIFFERENT parts of the tree yet change together 70% of the time (7 of the 10 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 7 shared commits counted here, the most recent 3 are `4dd038f1` chore(function): expose created_at and created_at_cluster_version for…; `0cc54b3f` feat(udf): introduce async and batched JavaScript UDF (#20403); `94154c03` refactor(udf): remove `function_type` field previously used by Deno U… — run `git show` on any of them.
Boundary-crossing change coupling: REDACTED ↔ parser.rs src/frontend/src/handler/mod.rs— `src/frontend/src/handler/mod.rs` (context handler) and `src/sqlparser/src/parser.rs` (context sqlparser) sit in DIFFERENT parts of the tree yet change together 68% of the time (83 of the 122 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 83 shared commits counted here, the most recent 3 are `7897e558` feat(storage): support runtime file cache clearing (#26577); `013bc9c9` feat(meta): support typed fragment rate limits (#26183); `b927f6c8` feat(ddl): support resource group alter for databases, sinks and inde… — run `git show` on any of them.
Boundary-crossing change coupling: hummock_service.rs ↔ hummock_meta_client.rs src/meta/service/src/hummock_service.rs— `src/meta/service/src/hummock_service.rs` (context meta) and `src/storage/src/hummock/hummock_meta_client.rs` (context storage) sit in DIFFERENT parts of the tree yet change together 67% of the time (10 of the 15 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 10 shared commits counted here, the most recent 3 are `68694f40` feat(compaction): support manual compact target level (#25765); `78494334` refactor(meta): improve the determinism of trigger_manual_compaction …; `1611e1bf` feat(proto): introduce iceberg compaction proto (#21778) — run `git show` on any of them.
Boundary-crossing change coupling: alter_streaming_rate_limit.rs ↔ parser.rs src/frontend/src/handler/alter_streaming_rate_limit.rs— `src/frontend/src/handler/alter_streaming_rate_limit.rs` (context handler) and `src/sqlparser/src/parser.rs` (context sqlparser) sit in DIFFERENT parts of the tree yet change together 67% of the time (8 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `91a0a91c` feat(frontend): support sink backfill rate limit (#24075); `9cc5d229` feat(frontend,meta): support alter fragment rate limit (#20795); `68c38d7b` revert:feat(frontend): support alter source pause/resume (#19636) (#2… — run `git show` on any of them.
Boundary-crossing change coupling: alter_streaming_rate_limit.rs ↔ ddl.rs src/frontend/src/handler/alter_streaming_rate_limit.rs— `src/frontend/src/handler/alter_streaming_rate_limit.rs` (context handler) and `src/sqlparser/src/ast/ddl.rs` (context sqlparser) sit in DIFFERENT parts of the tree yet change together 67% of the time (8 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `91a0a91c` feat(frontend): support sink backfill rate limit (#24075); `9cc5d229` feat(frontend,meta): support alter fragment rate limit (#20795); `68c38d7b` revert:feat(frontend): support alter source pause/resume (#19636) (#2… — run `git show` on any of them.
Boundary-crossing change coupling: SinkWriterStreamObserver.java ↔ connector_client.rs java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/SinkWriterStreamObserver.java— `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/SinkWriterStreamObserver.java` (context java) and `src/rpc_client/src/connector_client.rs` (context rpc_client) sit in DIFFERENT parts of the tree yet change together 67% of the time (8 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `ff495144` fix: deprecate `SinkPayloadFormat` (#16723); `f47a892e` feat(sink): support es sink struct and refactor es sink (#14231); `27fbce9f` refactor(sink): remove unnecessary StartEpoch of remote sink (#13806) — run `git show` on any of them.
Boundary-crossing change coupling: parser.rs ↔ pg_response.rs src/sqlparser/src/parser.rs— `src/sqlparser/src/parser.rs` (context sqlparser) and `src/utils/pgwire/src/pg_response.rs` (context utils) sit in DIFFERENT parts of the tree yet change together 65% of the time (17 of the 26 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 17 shared commits counted here, the most recent 3 are `feb8d927` feat: support alter compaction group config via sql (#24346); `fa7a8840` feat(meta): support wait jobs (#25133); `38175bba` feat(sql): add BACKUP and delete meta snapshot commands (#25042) — run `git show` on any of them.
Boundary-crossing change coupling: hummock_service.rs ↔ meta_client.rs src/meta/service/src/hummock_service.rs— `src/meta/service/src/hummock_service.rs` (context meta) and `src/rpc_client/src/meta_client.rs` (context rpc_client) sit in DIFFERENT parts of the tree yet change together 65% of the time (24 of the 37 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 24 shared commits counted here, the most recent 3 are `68694f40` feat(compaction): support manual compact target level (#25765); `78494334` refactor(meta): improve the determinism of trigger_manual_compaction …; `1611e1bf` feat(proto): introduce iceberg compaction proto (#21778) — run `git show` on any of them.
Boundary-crossing change coupling: binary_op.rs ↔ pure.rs src/frontend/src/binder/expr/binary_op.rs— `src/frontend/src/binder/expr/binary_op.rs` (context binder) and `src/frontend/src/expr/pure.rs` (context expr) sit in DIFFERENT parts of the tree yet change together 64% of the time (16 of the 25 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 16 shared commits counted here, the most recent 3 are `4339a18e` feat(expr): support array overlap predicates (#25597); `0444a8fc` feat(expr): `vector || vector` concatenation (#22745); `99a1c26d` feat(expr): more `vector` distance functions (#22647) — run `git show` on any of them.
Boundary-crossing change coupling: desc.rs ↔ create_source.rs src/connector/src/source/reader/desc.rs— `src/connector/src/source/reader/desc.rs` (context connector) and `src/frontend/src/handler/create_source.rs` (context handler) sit in DIFFERENT parts of the tree yet change together 64% of the time (14 of the 22 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 14 shared commits counted here, the most recent 3 are `ba225b21` fix(planner): correctly handle hidden columns for SourceBackfill (#19…; `8fe655f9` refactor: minor refactor on source column desc (#17417); `1401d56c` feat(cdc): support INCLUDE TIMESTAMP for MySQL, PG and MongoDB cdc ta… — run `git show` on any of them.
Boundary-crossing change coupling: REDACTED ↔ utils.rs src/object_store/src/object/opendal_engine/mod.rs— `src/object_store/src/object/opendal_engine/mod.rs` (context object_store) and `src/risedevtool/src/task/utils.rs` (context risedevtool) sit in DIFFERENT parts of the tree yet change together 64% of the time (7 of the 11 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) — the bounded-context boundary may be in the wrong place, or one context is leaking into the other. This is the behavioural boundary violation a static scan can't see. You can check this without leaving the row: of the 7 shared commits counted here, the most recent 3 are `ddfa85b2` feat(object store): support obs (#13844); `83057e5c` feat(storage): support azblob (#8257); `7641b15f` feat(test): add e2e test for OpenDAL fs backend (#8528) — run `git show` on any of them.
Orphaned knowledge src/meta/src/stream/stream_graph/assignment.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresConnectorConfig.java— No living knowledge remains for this large file — its last meaningful change has decayed away; if it breaks, no one currently understands it. Schedule a read-through / add characterisation tests before it bites.
Orphaned knowledge src/stream/src/executor/over_window/frame_finder.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/error/src/code.rs— No living knowledge remains for this large file — its last meaningful change has decayed away; if it breaks, no one currently understands it. Schedule a read-through / add characterisation tests before it bites.
Orphaned knowledge java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/connection/pgoutput/PgOutputMessageDecoder.java— No living knowledge remains for this large file — its last meaningful change has decayed away; if it breaks, no one currently understands it. Schedule a read-through / add characterisation tests before it bites.
Orphaned knowledge src/utils/resource_util/src/lib.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/meta/src/rpc/election/sql.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/expr/impl/src/scalar/cmp.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge e2e_test/check_slt_coverage.py— No living knowledge remains for this large file — its last meaningful change has decayed away; if it breaks, no one currently understands it. Schedule a read-through / add characterisation tests before it bites.
Orphaned knowledge src/frontend/src/expr/utils.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/storage/hummock_trace/src/replay/worker.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/utils/delta_btree_map/src/lib.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/meta/model/migration/src/m20260311_000000_legacy_streaming_parallelism_session_params.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/expr/impl/src/scalar/trigonometric.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/frontend/src/optimizer/delta_join_solver.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge src/frontend/src/optimizer/property/func_dep.rs— No living knowledge remains for this large file — its last meaningful change has decayed away, so if it breaks, no one currently understands it. It does carry its own tests, so the behaviour is pinned even though the understanding is gone: schedule a read-through, using those tests as the specification, before the next change lands here.
Orphaned knowledge grafana/dashboard/dev/hummock_read.py— No living knowledge remains for this large file — its last meaningful change has decayed away; if it breaks, no one currently understands it. Schedule a read-through / add characterisation tests before it bites.
DM4 · Rich vs anemic domain model· Anemic domain model · ×5
Anemic domain model: BatchManagerMetrics src/batch/src/monitor/stats.rs:111— `BatchManagerMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside.
Anemic domain model: BatchSpillMetrics src/batch/src/monitor/stats.rs:154— `BatchSpillMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside.
Anemic domain model: DistributedQueryMetrics src/frontend/src/scheduler/distributed/stats.rs:26— `DistributedQueryMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside.
Anemic domain model: RefreshCycleActors src/meta/src/stream/refresh_manager.rs:59— `RefreshCycleActors` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside.
Anemic domain model: HummockStateStoreMetrics src/storage/src/monitor/hummock_state_store_metrics.rs:43— `HummockStateStoreMetrics` is a data-only domain entity with `pub` mutable state and no invariant-enforcing behaviour of its own, while the repo holds the logic in a foreign service/manager/use-case — the anemic domain model. Move the behaviour onto the entity so it enforces its own invariants (or make it an immutable value object with private fields) rather than being driven from outside.
MethodTooLong: DatabaseCheckpointControl.apply_command src/meta/src/barrier/checkpoint/state.rs:432— MethodTooLong — apply_command runs 1039 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 939 over it, 10.39× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: StreamingMetrics.new src/stream/src/executor/monitor/streaming_stats.rs:273— MethodTooLong — new runs 1000 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 900 over it, 10.00× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: Migration.up src/meta/model/migration/src/m20230908_072257_init.rs:12— MethodTooLong — up runs 859 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 759 over it, 8.59× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: MetaMetrics.new src/meta/src/rpc/metrics.rs:279— MethodTooLong — new runs 643 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 543 over it, 6.43× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: Statement.fmt_unchecked src/sqlparser/src/ast/mod.rs:1801— MethodTooLong — fmt_unchecked runs 624 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 524 over it, 6.24× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: Binder.bind_builtin_scalar_function src/frontend/src/binder/expr/function/builtin_scalar.rs:31— MethodTooLong — bind_builtin_scalar_function runs 598 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 498 over it, 5.98× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: ParallelizedCdcBackfillExecutor.execute_inner src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:114— MethodTooLong — execute_inner runs 480 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 380 over it, 4.80× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: PartialGraphRecoverer.inject_database_initial_barrier src/meta/src/barrier/rpc.rs:619— MethodTooLong — inject_database_initial_barrier runs 468 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 368 over it, 4.68× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: CdcBackfillExecutor.execute_inner src/stream/src/executor/backfill/cdc/cdc_backfill.rs:329— MethodTooLong — execute_inner runs 467 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 367 over it, 4.67× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: HummockStateStoreMetrics.new src/storage/src/monitor/hummock_state_store_metrics.rs:114— MethodTooLong — new runs 427 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 327 over it, 4.27× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: FunctionAttr.generate_build_scalar_function src/expr/macro/src/gen.rs:198— MethodTooLong — generate_build_scalar_function runs 392 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 292 over it, 3.92× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: JsonParseOptions.parse src/connector/src/parser/unified/json.rs:277— MethodTooLong — parse runs 377 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 277 over it, 3.77× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: SourceBackfillExecutorInner.execute src/stream/src/executor/source/source_backfill_executor.rs:383— MethodTooLong — execute runs 370 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 270 over it, 3.70× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: SourceExecutor.execute_inner src/stream/src/executor/source/source_executor.rs:616— MethodTooLong — execute_inner runs 339 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 239 over it, 3.39× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: MaterializeExecutor.execute_inner src/stream/src/executor/mview/materialize.rs:373— MethodTooLong — execute_inner runs 323 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 223 over it, 3.23× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: CatalogController.update_connection_and_dependent_objects_props src/meta/src/controller/streaming_job.rs:3280— MethodTooLong — update_connection_and_dependent_objects_props runs 318 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 218 over it, 3.18× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: ArrangementBackfillExecutor.execute_inner src/stream/src/executor/backfill/arrangement_backfill.rs:109— MethodTooLong — execute_inner runs 317 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 217 over it, 3.17× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: ImpureAnalyzer.visit_function_call src/frontend/src/expr/pure.rs:100— MethodTooLong — visit_function_call runs 304 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 204 over it, 3.04× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: Strong.is_null_function_call src/frontend/src/optimizer/plan_expr_visitor/strong.rs:76— MethodTooLong — is_null_function_call runs 297 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 197 over it, 2.97× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: GlobalBarrierWorker.recovery_inner src/meta/src/barrier/worker.rs:1140— MethodTooLong — recovery_inner runs 291 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 191 over it, 2.91× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: LocalQueryExecution.convert_plan_node src/frontend/src/scheduler/local.rs:260— MethodTooLong — convert_plan_node runs 283 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 183 over it, 2.83× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: SnapshotBackfillExecutor.execute_inner src/stream/src/executor/backfill/snapshot_backfill/executor.rs:163— MethodTooLong — execute_inner runs 283 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 183 over it, 2.83× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: CatalogController.create_job_catalog src/meta/src/controller/streaming_job.rs:467— MethodTooLong — create_job_catalog runs 279 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 179 over it, 2.79× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: CatalogController.alter_owner src/meta/src/controller/catalog/alter_op.rs:281— MethodTooLong — alter_owner runs 270 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 170 over it, 2.70× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
MethodTooLong: GlobalBarrierWorker.run_inner src/meta/src/barrier/worker.rs:516— MethodTooLong — run_inner runs 269 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 169 over it, 2.69× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FileTooLong: src/parser.rs src/sqlparser/src/parser.rs— FileTooLong — 4594 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 97% of them inside a single declaration: Parser (198-6878). The bar is 500 significant lines; this is 4094 over it, 9.19× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: controller/streaming_job.rs src/meta/src/controller/streaming_job.rs— FileTooLong — 2988 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 89% of them inside a single declaration: CatalogController (241-3922). The bar is 500 significant lines; this is 2488 over it, 5.98× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: ast/mod.rs src/sqlparser/src/ast/mod.rs— FileTooLong — 2657 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 2157 over it, 5.31× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: src/meta_client.rs src/rpc_client/src/meta_client.rs— FileTooLong — 2155 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 74% of them inside a single declaration: MetaClient (4 blocks, 141-2286). The bar is 500 significant lines; this is 1655 over it, 4.31× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: controller/utils.rs src/meta/src/controller/utils.rs— FileTooLong — 1962 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), declaring 61 free functions. The bar is 500 significant lines; this is 1462 over it, 3.92× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: rpc/ddl_controller.rs src/meta/src/rpc/ddl_controller.rs— FileTooLong — 1959 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 82% of them inside a single declaration: DdlController (2 blocks, 283-2519). The bar is 500 significant lines; this is 1459 over it, 3.92× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: join/hash_join.rs src/batch/executors/src/executor/join/hash_join.rs— FileTooLong — 1729 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 73% of them inside a single declaration: HashJoinExecutor (5 blocks, 64-2514). The bar is 500 significant lines; this is 1229 over it, 3.46× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: table/state_table.rs src/stream/src/common/table/state_table.rs— FileTooLong — 1651 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 1151 over it, 3.30× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: monitor/streaming_stats.rs src/stream/src/executor/monitor/streaming_stats.rs— FileTooLong — 1605 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 93% of them inside a single declaration: StreamingMetrics (2 blocks, 45-1969). The bar is 500 significant lines; this is 1105 over it, 3.21× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: controller/fragment.rs src/meta/src/controller/fragment.rs— FileTooLong — 1579 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 88% of them inside a single declaration: CatalogController (290-2158). The bar is 500 significant lines; this is 1079 over it, 3.16× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: handler/create_table.rs src/frontend/src/handler/create_table.rs— FileTooLong — 1568 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 1068 over it, 3.14× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: src/ddl_service.rs src/meta/service/src/ddl_service.rs— FileTooLong — 1557 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 92% of them inside a single declaration: DdlServiceImpl (3 blocks, 69-2006). The bar is 500 significant lines; this is 1057 over it, 3.11× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: stream_graph/fragment.rs src/meta/src/stream/stream_graph/fragment.rs— FileTooLong — 1429 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 929 over it, 2.86× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: handler/mod.rs src/frontend/src/handler/mod.rs— FileTooLong — 1426 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 926 over it, 2.85× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: src/session.rs src/frontend/src/session.rs— FileTooLong — 1350 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 850 over it, 2.70× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: checkpoint/state.rs src/meta/src/barrier/checkpoint/state.rs— FileTooLong — 1305 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 82% of them inside a single declaration: DatabaseCheckpointControl (381-1849). The bar is 500 significant lines; this is 805 over it, 2.61× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: compaction/mod.rs src/meta/src/hummock/manager/compaction/mod.rs— FileTooLong — 1297 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 67% of them inside a single declaration: HummockManager (4 blocks, 207-1452). The bar is 500 significant lines; this is 797 over it, 2.59× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: rpc/metrics.rs src/meta/src/rpc/metrics.rs— FileTooLong — 1256 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 756 over it, 2.51× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: arrow/arrow_impl.rs src/common/src/array/arrow/arrow_impl.rs— FileTooLong — 1225 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 725 over it, 2.45× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: uploader/mod.rs src/storage/src/hummock/event_handler/uploader/mod.rs— FileTooLong — 1219 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 719 over it, 2.44× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: plan_node/logical_join.rs src/frontend/src/optimizer/plan_node/logical_join.rs— FileTooLong — 1216 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 92% of them inside a single declaration: LogicalJoin (11 blocks, 58-1874). The bar is 500 significant lines; this is 716 over it, 2.43× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: compactor/mod.rs src/storage/src/hummock/compactor/mod.rs— FileTooLong — 1212 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 712 over it, 2.42× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: controller/scale.rs src/meta/src/controller/scale.rs— FileTooLong — 1183 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 683 over it, 2.37× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FileTooLong: barrier/command.rs src/meta/src/barrier/command.rs— FileTooLong — 1166 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), about 66% of them inside a single declaration: Command (6 blocks, 463-1790). The bar is 500 significant lines; this is 666 over it, 2.33× the bar. Moving the declarations that sit BESIDE it into sibling files will not shorten this file. Extract from INSIDE that declaration instead: lift each cohesive group of its body — the parts that share the same inputs and are named together — into its own unit in a sibling file, and have the original call them.
FileTooLong: relation/match_recognize.rs src/frontend/src/binder/relation/match_recognize.rs— FileTooLong — 1150 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted). The bar is 500 significant lines; this is 650 over it, 2.30× the bar. To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them.
FunctionTooLong: risingwave_frontend::handler::handle src/frontend/src/handler/mod.rs:306— FunctionTooLong — risingwave_frontend::handler::handle runs 1105 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 1005 over it, 11.05× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_meta_node::server::start_service_as_election_leader src/meta/node/src/server.rs:313— FunctionTooLong — risingwave_meta_node::server::start_service_as_election_leader runs 402 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 302 over it, 4.02× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_storage::hummock::compactor::start_iceberg_compactor src/storage/src/hummock/compactor/mod.rs:400— FunctionTooLong — risingwave_storage::hummock::compactor::start_iceberg_compactor runs 384 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 284 over it, 3.84× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: FragmentGraph.FragmentGraph dashboard/components/FragmentGraph.tsx:92— FunctionTooLong — FragmentGraph runs 374 significant lines (blank, comment-only and punctuation-only lines excluded) in one body. The bar is 100 significant lines; this is 274 over it, 3.74× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::expr::type_inference::func::infer_type_for_special src/frontend/src/expr/type_inference/func.rs:323— FunctionTooLong — risingwave_frontend::expr::type_inference::func::infer_type_for_special runs 349 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 249 over it, 3.49× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_ctl::start_impl src/ctl/src/lib.rs:666— FunctionTooLong — risingwave_ctl::start_impl runs 342 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 242 over it, 3.42× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_compute::server::compute_node_serve src/compute/src/server.rs:93— FunctionTooLong — risingwave_compute::server::compute_node_serve runs 318 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 218 over it, 3.18× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risedev::bin::risedev-dev::task_main src/risedevtool/src/bin/risedev-dev.rs:66— FunctionTooLong — risedev::bin::risedev-dev::task_main runs 311 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 211 over it, 3.11× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::handler::create_sink::gen_sink_plan src/frontend/src/handler/create_sink.rs:151— FunctionTooLong — risingwave_frontend::handler::create_sink::gen_sink_plan runs 297 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 197 over it, 2.97× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risedev::risedev_env::generate_risedev_env src/risedevtool/src/risedev_env.rs:25— FunctionTooLong — risedev::risedev_env::generate_risedev_env runs 272 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 172 over it, 2.72× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::handler::show::handle_show_object src/frontend/src/handler/show.rs:501— FunctionTooLong — risingwave_frontend::handler::show::handle_show_object runs 271 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 171 over it, 2.71× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: RelationGraph.RelationGraph dashboard/components/RelationGraph.tsx:73— FunctionTooLong — RelationGraph runs 266 significant lines (blank, comment-only and punctuation-only lines excluded) in one body. The bar is 100 significant lines; this is 166 over it, 2.66× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::handler::explain::do_handle_explain src/frontend/src/handler/explain.rs:49— FunctionTooLong — risingwave_frontend::handler::explain::do_handle_explain runs 262 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 162 over it, 2.62× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::handler::create_index::gen_create_index_plan src/frontend/src/handler/create_index.rs:143— FunctionTooLong — risingwave_frontend::handler::create_index::gen_create_index_plan runs 253 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 153 over it, 2.53× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::handler::create_table::create_iceberg_engine_table src/frontend/src/handler/create_table.rs:1453— FunctionTooLong — risingwave_frontend::handler::create_table::create_iceberg_engine_table runs 248 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 148 over it, 2.48× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_common_proc_macro::session_config::derive_config src/common/proc_macro/src/session_config.rs:31— FunctionTooLong — risingwave_common_proc_macro::session_config::derive_config runs 247 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 147 over it, 2.47× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_storage::hummock::compactor::start_compactor src/storage/src/hummock/compactor/mod.rs:951— FunctionTooLong — risingwave_storage::hummock::compactor::start_compactor runs 244 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 144 over it, 2.44× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_rt::logger::init_risingwave_logger src/utils/runtime/src/logger.rs:235— FunctionTooLong — risingwave_rt::logger::init_risingwave_logger runs 235 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 135 over it, 2.35× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::handler::handle_privilege::make_prost_privilege src/frontend/src/handler/handle_privilege.rs:46— FunctionTooLong — risingwave_frontend::handler::handle_privilege::make_prost_privilege runs 233 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 133 over it, 2.33× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: fragment_graph.Streaming dashboard/pages/fragment_graph.tsx:227— FunctionTooLong — Streaming runs 232 significant lines (blank, comment-only and punctuation-only lines excluded) in one body. The bar is 100 significant lines; this is 132 over it, 2.32× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_storage::hummock::compactor::compactor_runner::compact_with_agent src/storage/src/hummock/compactor/compactor_runner.rs:323— FunctionTooLong — risingwave_storage::hummock::compactor::compactor_runner::compact_with_agent runs 211 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 111 over it, 2.11× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_storage::hummock::compactor::iceberg_compaction::memory::estimate_plan_memory src/storage/src/hummock/compactor/iceberg_compaction/memory.rs:59— FunctionTooLong — risingwave_storage::hummock::compactor::iceberg_compaction::memory::estimate_plan_memory runs 210 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 110 over it, 2.10× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_compute::memory::config::storage_memory_config src/compute/src/memory/config.rs:107— FunctionTooLong — risingwave_compute::memory::config::storage_memory_config runs 201 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 101 over it, 2.01× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: heap_profiling.HeapProfiling dashboard/pages/heap_profiling.tsx:75— FunctionTooLong — HeapProfiling runs 195 significant lines (blank, comment-only and punctuation-only lines excluded) in one body. The bar is 100 significant lines; this is 95 over it, 1.95× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
FunctionTooLong: risingwave_frontend::handler::create_source::external_schema::bind_columns_from_source_for_non_cdc src/frontend/src/handler/create_source/external_schema.rs:92— FunctionTooLong — risingwave_frontend::handler::create_source::external_schema::bind_columns_from_source_for_non_cdc runs 193 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted) in one body. The bar is 100 significant lines; this is 93 over it, 1.93× the bar. This is length, not branching: a long straight-line body scores low on complexity and is still read whole to change any part of it, so the complexity numbers beside this row neither confirm nor excuse it. To reduce it, extract each cohesive step of the body — the runs of statements that work on the same values and would earn the same name — into its own named unit, and have this one call them in order.
ClassTooLong: Parser src/sqlparser/src/parser.rs:196— ClassTooLong — 4471 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 248 methods. The bar is 400 significant lines; this is 4071 over it, 11.18× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: DdlController src/meta/src/rpc/ddl_controller.rs:283— ClassTooLong — 1608 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 51 methods, 2 blocks, lines 283-2519. The bar is 400 significant lines; this is 1208 over it, 4.02× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: MetaClient src/rpc_client/src/meta_client.rs:141— ClassTooLong — 1591 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 152 methods, 4 blocks, lines 141-2286. The bar is 400 significant lines; this is 1191 over it, 3.98× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: StreamingMetrics src/stream/src/executor/monitor/streaming_stats.rs:45— ClassTooLong — 1492 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 18 methods, 2 blocks, lines 45-1969. The bar is 400 significant lines; this is 1092 over it, 3.73× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: DdlServiceImpl src/meta/service/src/ddl_service.rs:69— ClassTooLong — 1431 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 4 methods, 3 blocks, lines 69-2006. The bar is 400 significant lines; this is 1031 over it, 3.58× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: HashJoinExecutor src/batch/executors/src/executor/join/hash_join.rs:64— ClassTooLong — 1264 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 29 methods, 5 blocks, lines 64-2514. The bar is 400 significant lines; this is 864 over it, 3.16× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: LogicalJoin src/frontend/src/optimizer/plan_node/logical_join.rs:58— ClassTooLong — 1120 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 43 methods, 11 blocks, lines 58-1874. The bar is 400 significant lines; this is 720 over it, 2.80× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: PostgresConnectorConfig java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresConnectorConfig.java:62— ClassTooLong — 1001 significant lines (blank, comment-only and punctuation-only lines excluded), 43 methods. The bar is 400 significant lines; this is 601 over it, 2.50× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: Statement src/sqlparser/src/ast/mod.rs:1276— ClassTooLong — 932 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 6 methods, 4 blocks, lines 1276-4033. The bar is 400 significant lines; this is 532 over it, 2.33× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: Migration src/meta/model/migration/src/m20230908_072257_init.rs:8— ClassTooLong — 886 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 0 methods. The bar is 400 significant lines; this is 486 over it, 2.22× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: DiagnoseCommand src/meta/src/manager/diagnose.rs:53— ClassTooLong — 883 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 18 methods, 2 blocks, lines 53-1199. The bar is 400 significant lines; this is 483 over it, 2.21× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: HashJoinExecutor src/stream/src/executor/hash_join.rs:158— ClassTooLong — 883 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 14 methods, 4 blocks, lines 158-1404. The bar is 400 significant lines; this is 483 over it, 2.21× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: GlobalBarrierWorker src/meta/src/barrier/worker.rs:86— ClassTooLong — 863 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 16 methods, 9 blocks, lines 86-1526. The bar is 400 significant lines; this is 463 over it, 2.16× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: Catalog src/frontend/src/catalog/root_catalog.rs:122— ClassTooLong — 862 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 86 methods, 3 blocks, lines 122-1276. The bar is 400 significant lines; this is 462 over it, 2.16× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: BatchRefreshJobCheckpointControl src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs:197— ClassTooLong — 814 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 20 methods, 8 blocks, lines 197-1464. The bar is 400 significant lines; this is 414 over it, 2.04× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: SchemaCatalog src/frontend/src/catalog/schema_catalog.rs:46— ClassTooLong — 785 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 99 methods, 4 blocks, lines 46-1159. The bar is 400 significant lines; this is 385 over it, 1.96× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: StreamServiceImpl src/meta/service/src/stream_service.rs:61— ClassTooLong — 780 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 1 methods, 3 blocks, lines 61-1121. The bar is 400 significant lines; this is 380 over it, 1.95× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: CreatingStreamingJobControl src/meta/src/barrier/checkpoint/independent_job/creating_job/mod.rs:85— ClassTooLong — 778 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 21 methods, 3 blocks, lines 85-1104. The bar is 400 significant lines; this is 378 over it, 1.95× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: Command src/meta/src/barrier/command.rs:463— ClassTooLong — 765 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 25 methods, 6 blocks, lines 463-1790. The bar is 400 significant lines; this is 365 over it, 1.91× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: Condition src/frontend/src/utils/condition.rs:40— ClassTooLong — 748 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 30 methods, 4 blocks, lines 40-1222. The bar is 400 significant lines; this is 348 over it, 1.87× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: MetaMetrics src/meta/src/rpc/metrics.rs:73— ClassTooLong — 741 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 1 methods, 3 blocks, lines 73-1110. The bar is 400 significant lines; this is 341 over it, 1.85× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: PgProtocol src/utils/pgwire/src/pg_protocol.rs:72— ClassTooLong — 720 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 30 methods, 3 blocks, lines 72-1308. The bar is 400 significant lines; this is 320 over it, 1.80× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: BatchTableInner src/storage/src/table/batch_table/mod.rs:265— ClassTooLong — 709 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 31 methods, 6 blocks, lines 265-1351. The bar is 400 significant lines; this is 309 over it, 1.77× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: MaterializeExecutor src/stream/src/executor/mview/materialize.rs:68— ClassTooLong — 684 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 5 methods, 5 blocks, lines 68-1212. The bar is 400 significant lines; this is 284 over it, 1.71× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
ClassTooLong: SourceExecutor src/stream/src/executor/source/source_executor.rs:98— ClassTooLong — 683 significant lines (blank, comment-only and punctuation-only lines excluded, and inline test code — #[cfg(test)] modules and bare #[test] functions — not counted), 15 methods, 4 blocks, lines 98-1173. The bar is 400 significant lines; this is 283 over it, 1.71× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
Hotspot: src/meta/src/barrier/checkpoint/state.rs src/meta/src/barrier/checkpoint/state.rs:432— src/meta/src/barrier/checkpoint/state.rs changed 15 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 79 in DatabaseCheckpointControl::apply_command at line 432. 6 of those changes were fix/bug commits, and the other 9 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/checkpoint/state.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/sqlparser/src/ast/mod.rs src/sqlparser/src/ast/mod.rs:1801— src/sqlparser/src/ast/mod.rs changed 7 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 148 in Statement::fmt_unchecked at line 1801. 1 of those changes was a fix/bug commit, and the other 6 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/sqlparser/src/ast/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/frontend/src/handler/mod.rs src/frontend/src/handler/mod.rs:306— src/frontend/src/handler/mod.rs changed 5 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 181 in risingwave_frontend::handler::handle at line 306. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/frontend/src/handler/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/meta/src/barrier/worker.rs src/meta/src/barrier/worker.rs:516— src/meta/src/barrier/worker.rs changed 15 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 52 in GlobalBarrierWorker::run_inner at line 516. 9 of those changes were fix/bug commits, so the churn is repair rather than feature work. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/worker.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/stream/src/executor/backfill/cdc/cdc_backfill.rs src/stream/src/executor/backfill/cdc/cdc_backfill.rs:329— src/stream/src/executor/backfill/cdc/cdc_backfill.rs changed 8 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 64 in CdcBackfillExecutor::execute_inner at line 329. 4 of those changes were fix/bug commits, and the other 4 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/stream/src/executor/backfill/cdc/cdc_backfill.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/meta/src/controller/streaming_job.rs src/meta/src/controller/streaming_job.rs:467— src/meta/src/controller/streaming_job.rs changed 19 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 25 in CatalogController::create_job_catalog at line 467. 9 of those changes were fix/bug commits, and the other 10 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/controller/streaming_job.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/connector/src/connector_common/iceberg/mod.rs src/connector/src/connector_common/iceberg/mod.rs:766— src/connector/src/connector_common/iceberg/mod.rs changed 6 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 71 in IcebergCommon::build_jni_catalog_configs at line 766. 2 of those changes were fix/bug commits, and the other 4 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/connector/src/connector_common/iceberg/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/meta/src/rpc/ddl_controller.rs src/meta/src/rpc/ddl_controller.rs:444— src/meta/src/rpc/ddl_controller.rs changed 12 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 32 in DdlController::run_command at line 444. 5 of those changes were fix/bug commits, and the other 7 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/rpc/ddl_controller.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:114— src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs changed 4 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 90 in ParallelizedCdcBackfillExecutor::execute_inner at line 114. 1 of those changes was a fix/bug commit, and the other 3 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/storage/src/hummock/compactor/mod.rs src/storage/src/hummock/compactor/mod.rs:400— src/storage/src/hummock/compactor/mod.rs changed 9 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 38 in risingwave_storage::hummock::compactor::start_iceberg_compactor at line 400. 2 of those changes were fix/bug commits, and the other 7 changed it for other reasons — this file is under both repair and feature pressure. Before the next change lands here, make sure the area it touches is under test, then split that area out of the file so the following change is smaller than this one — a file this often edited pays the complexity back every time. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/storage/src/hummock/compactor/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/frontend/src/handler/create_sink.rs src/frontend/src/handler/create_sink.rs:151— src/frontend/src/handler/create_sink.rs changed 6 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 53 in risingwave_frontend::handler::create_sink::gen_sink_plan at line 151. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/frontend/src/handler/create_sink.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/meta/src/barrier/checkpoint/control.rs src/meta/src/barrier/checkpoint/control.rs:236— src/meta/src/barrier/checkpoint/control.rs changed 16 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 18 in CheckpointControl::handle_new_barrier at line 236. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/checkpoint/control.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/common/src/array/arrow/arrow_impl.rs src/common/src/array/arrow/arrow_impl.rs:648— src/common/src/array/arrow/arrow_impl.rs changed 7 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 39 in FromArrow::from_array at line 648. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/common/src/array/arrow/arrow_impl.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/meta/src/barrier/rpc.rs src/meta/src/barrier/rpc.rs:619— src/meta/src/barrier/rpc.rs changed 14 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 19 in PartialGraphRecoverer::inject_database_initial_barrier at line 619. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/rpc.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/ctl/src/lib.rs src/ctl/src/lib.rs:666— src/ctl/src/lib.rs changed 4 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 61 in risingwave_ctl::start_impl at line 666. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/ctl/src/lib.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/meta/src/barrier/context/context_impl.rs src/meta/src/barrier/context/context_impl.rs:634— src/meta/src/barrier/context/context_impl.rs changed 11 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 22 in PostCollectCommand::post_collect at line 634. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/context/context_impl.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/connector/src/parser/unified/json.rs src/connector/src/parser/unified/json.rs:277— src/connector/src/parser/unified/json.rs changed 3 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 74 in JsonParseOptions::parse at line 277. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/connector/src/parser/unified/json.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/stream/src/executor/mod.rs src/stream/src/executor/mod.rs:1015— src/stream/src/executor/mod.rs changed 13 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 17 in Mutation::from_protobuf at line 1015. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/stream/src/executor/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/meta/service/src/ddl_service.rs src/meta/service/src/ddl_service.rs:1340— src/meta/service/src/ddl_service.rs changed 11 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 20 in DdlServiceImpl::auto_schema_change at line 1340. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/service/src/ddl_service.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/common/src/system_param/mod.rs src/common/src/system_param/mod.rs:329— src/common/src/system_param/mod.rs changed 3 times in last 90 days, max cyclomatic complexity 73 in risingwave_common::system_param::set_system_param at line 329. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/common/src/system_param/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/stream/src/executor/source/source_executor.rs src/stream/src/executor/source/source_executor.rs:616— src/stream/src/executor/source/source_executor.rs changed 4 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 53 in SourceExecutor::execute_inner at line 616. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/stream/src/executor/source/source_executor.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/risedevtool/src/bin/risedev-dev.rs src/risedevtool/src/bin/risedev-dev.rs:66— src/risedevtool/src/bin/risedev-dev.rs changed 6 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 35 in risedev::bin::risedev-dev::task_main at line 66. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/risedevtool/src/bin/risedev-dev.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/frontend/src/optimizer/plan_node/stream_sink.rs src/frontend/src/optimizer/plan_node/stream_sink.rs:280— src/frontend/src/optimizer/plan_node/stream_sink.rs changed 4 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 49 in StreamSink::create at line 280. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/frontend/src/optimizer/plan_node/stream_sink.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/connector/src/sink/iceberg/config.rs src/connector/src/sink/iceberg/config.rs:578— src/connector/src/sink/iceberg/config.rs changed 8 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 24 in IcebergConfig::from_btreemap at line 578. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/connector/src/sink/iceberg/config.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Hotspot: src/connector/src/connector_common/postgres.rs src/connector/src/connector_common/postgres.rs:671— src/connector/src/connector_common/postgres.rs changed 7 times in last 90 days, and the most complex body those changes touched has cyclomatic complexity 27 in risingwave_connector::connector_common::postgres::sea_type_to_rw_type at line 671. Frequent change and high complexity in one file compound: schedule the next change to it to include carving out the part being edited, with the area under test before it moves. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/connector/src/connector_common/postgres.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Duplicated block (8 lines × 2) src/batch/executors/src/executor/hash_agg.rs:498— src/batch/executors/src/executor/hash_agg.rs:498-505 | src/batch/executors/src/executor/order_by.rs:118-125 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/order_by.rs` as WHOLE FILES: this scan already matched 7 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8 lines × 2) src/batch/executors/src/executor/sort_agg.rs:154— src/batch/executors/src/executor/sort_agg.rs:154-161 | src/batch/executors/src/executor/sort_agg.rs:185-192 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/common/src/array/list_array.rs:810— src/common/src/array/list_array.rs:810-817 | src/common/src/array/list_array.rs:850-857 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/connector/src/connector_common/iceberg/jni_catalog.rs:378— src/connector/src/connector_common/iceberg/jni_catalog.rs:378-385 | src/connector/src/connector_common/iceberg/jni_catalog.rs:476-483 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/connector/src/sink/iceberg/commit.rs:855— src/connector/src/sink/iceberg/commit.rs:855-862 | src/connector/src/sink/iceberg/commit.rs:880-887 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/connector/src/sink/redis.rs:165— src/connector/src/sink/redis.rs:165-172 | src/connector/src/sink/redis.rs:174-181 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) REDACTED:118— REDACTED:118-125 | REDACTED:152-159 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/ctl/src/cmd_impl/hummock/validate_version.rs:78— src/ctl/src/cmd_impl/hummock/validate_version.rs:78-85 | src/ctl/src/cmd_impl/hummock/validate_version.rs:178-185 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/expr/impl/src/aggregate/approx_count_distinct/mod.rs:69— src/expr/impl/src/aggregate/approx_count_distinct/mod.rs:69-76 | src/expr/impl/src/aggregate/approx_count_distinct/mod.rs:131-138 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/expr/impl/src/aggregate/approx_count_distinct/mod.rs:85— src/expr/impl/src/aggregate/approx_count_distinct/mod.rs:85-92 | src/expr/impl/src/aggregate/approx_count_distinct/mod.rs:147-154 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/expr/impl/src/scalar/date_trunc.rs:46— src/expr/impl/src/scalar/date_trunc.rs:46-53 | src/expr/impl/src/scalar/date_trunc.rs:104-111 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/frontend/planner_test/src/lib.rs:699— src/frontend/planner_test/src/lib.rs:699-706 | src/frontend/planner_test/src/lib.rs:760-767 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/frontend/src/binder/relation/match_recognize.rs:1153— src/frontend/src/binder/relation/match_recognize.rs:1153-1160 | src/stream/src/executor/match_recognize/proto.rs:50-57 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (8 lines × 2) src/frontend/src/expr/session_timezone.rs:225— src/frontend/src/expr/session_timezone.rs:225-232 | src/frontend/src/expr/session_timezone.rs:238-245 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/frontend/src/expr/type_inference/func.rs:372— src/frontend/src/expr/type_inference/func.rs:372-379 | src/frontend/src/expr/type_inference/func.rs:389-396 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/frontend/src/optimizer/plan_node/stream_cdc_table_scan.rs:139— src/frontend/src/optimizer/plan_node/stream_cdc_table_scan.rs:139-146 | src/frontend/src/optimizer/plan_node/stream_table_scan.rs:354-361 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (8 lines × 2) src/frontend/src/optimizer/plan_node/stream_project.rs:84— src/frontend/src/optimizer/plan_node/stream_project.rs:84-91 | src/frontend/src/optimizer/plan_node/stream_project_set.rs:47-54 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (8 lines × 2) src/frontend/src/handler/alter_source_props.rs:110— src/frontend/src/handler/alter_source_props.rs:110-117 | src/frontend/src/handler/create_source/validate.rs:308-315 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (8 lines × 2) src/frontend/src/handler/drop_connection.rs:36— src/frontend/src/handler/drop_connection.rs:36-43 | src/frontend/src/handler/drop_table.rs:35-42 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (8 lines × 2) src/frontend/src/handler/create_aggregate.rs:123— src/frontend/src/handler/create_aggregate.rs:123-130 | src/frontend/src/handler/create_function.rs:178-185 — before extracting anything, compare `src/frontend/src/handler/create_aggregate.rs` and `src/frontend/src/handler/create_function.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 59 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8 lines × 2) src/frontend/src/handler/alter_mv.rs:42— src/frontend/src/handler/alter_mv.rs:42-49 | src/frontend/src/handler/alter_rename.rs:39-46 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (8 lines × 2) src/frontend/src/handler/comment.rs:52— src/frontend/src/handler/comment.rs:52-59 | src/frontend/src/handler/comment.rs:77-84 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/meta/service/src/ddl_service.rs:279— src/meta/service/src/ddl_service.rs:279-286 | src/meta/service/src/ddl_service.rs:318-325 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8 lines × 2) src/meta/src/barrier/command.rs:166— src/meta/src/barrier/command.rs:166-173 | src/meta/src/controller/scale.rs:313-320 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (8 lines × 2) src/meta/src/controller/catalog/mod.rs:553— src/meta/src/controller/catalog/mod.rs:553-560 | src/meta/src/controller/catalog/mod.rs:574-581 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/batch/executors/src/executor/hash_agg.rs:655— src/batch/executors/src/executor/hash_agg.rs:655-668 | src/batch/executors/src/executor/join/hash_join.rs:636-649 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/join/hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 81 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (14 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:1108— src/batch/executors/src/executor/join/hash_join.rs:1108-1121 | src/batch/executors/src/executor/join/hash_join.rs:1587-1600 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/connector/src/sink/encoder/template.rs:430— src/connector/src/sink/encoder/template.rs:430-443 | src/connector/src/sink/encoder/template.rs:448-461 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/connector/src/source/reader/fs_reader.rs:61— src/connector/src/source/reader/fs_reader.rs:61-74 | src/connector/src/source/reader/reader.rs:71-84 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (14 lines × 2) src/expr/impl/src/scalar/regexp.rs:403— src/expr/impl/src/scalar/regexp.rs:403-416 | src/expr/impl/src/scalar/regexp.rs:435-448 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/planner_test/src/lib.rs:343— src/frontend/planner_test/src/lib.rs:343-356 | src/frontend/planner_test/src/lib.rs:374-387 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/src/binder/select.rs:472— src/frontend/src/binder/select.rs:472-485 | src/frontend/src/binder/select.rs:517-530 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:653— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:653-666 | src/frontend/src/optimizer/rule/join_commute_rule.rs:88-101 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (14 lines × 2) src/frontend/src/optimizer/rule/table_function_to_internal_backfill_progress.rs:64— src/frontend/src/optimizer/rule/table_function_to_internal_backfill_progress.rs:64-77 | src/frontend/src/optimizer/rule/table_function_to_internal_source_backfill_progress.rs:62-75 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (14 lines × 2) src/frontend/src/scheduler/distributed/stage.rs:1071— src/frontend/src/scheduler/distributed/stage.rs:1071-1084 | src/frontend/src/scheduler/distributed/stage.rs:1091-1104 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/src/session/transaction.rs:162— src/frontend/src/session/transaction.rs:162-175 | src/frontend/src/session/transaction.rs:180-193 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/src/handler/create_source/external_schema.rs:344— src/frontend/src/handler/create_source/external_schema.rs:344-358 | src/frontend/src/handler/create_source/external_schema.rs:405-418 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/src/planner/relation.rs:174— src/frontend/src/planner/relation.rs:174-187 | src/frontend/src/planner/relation.rs:399-412 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/src/stream_fragmenter/rewrite/delta_join.rs:156— src/frontend/src/stream_fragmenter/rewrite/delta_join.rs:156-169 | src/frontend/src/stream_fragmenter/rewrite/delta_join.rs:185-198 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/frontend/src/handler/alter_database_param.rs:30— src/frontend/src/handler/alter_database_param.rs:30-43 | src/frontend/src/handler/alter_database_param.rs:83-96 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/controller/streaming_job.rs:669— src/meta/src/controller/streaming_job.rs:669-682 | src/meta/src/controller/streaming_job.rs:732-746 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/controller/streaming_job.rs:1306— src/meta/src/controller/streaming_job.rs:1306-1319 | src/meta/src/controller/streaming_job.rs:1893-1906 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/dashboard/mod.rs:545— src/meta/src/dashboard/mod.rs:545-558 | src/meta/src/dashboard/mod.rs:611-624 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/hummock/manager/time_travel.rs:478— src/meta/src/hummock/manager/time_travel.rs:478-491 | src/meta/src/hummock/manager/time_travel.rs:519-532 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/manager/diagnose.rs:829— src/meta/src/manager/diagnose.rs:829-842 | src/meta/src/manager/diagnose.rs:884-897 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/rpc/election/sql.rs:201— src/meta/src/rpc/election/sql.rs:201-214 | src/meta/src/rpc/election/sql.rs:551-564 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/stream/stream_manager.rs:950— src/meta/src/stream/stream_manager.rs:950-963 | src/meta/src/stream/stream_manager.rs:994-1007 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/backup_restore/utils.rs:42— src/meta/src/backup_restore/utils.rs:42-55 | src/meta/src/backup_restore/utils.rs:59-72 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/meta/src/controller/catalog/alter_op.rs:52— src/meta/src/controller/catalog/alter_op.rs:52-65 | src/meta/src/controller/catalog/alter_op.rs:886-899 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14 lines × 2) src/object_store/src/object/mod.rs:608— src/object_store/src/object/mod.rs:608-621 | src/object_store/src/object/mod.rs:720-733 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/batch/executors/src/executor/aggregation/orderby.rs:105— src/batch/executors/src/executor/aggregation/orderby.rs:105-111 | src/frontend/src/datafusion/aggregate/orderby.rs:106-112 — before extracting anything, compare `src/batch/executors/src/executor/aggregation/orderby.rs` and `src/frontend/src/datafusion/aggregate/orderby.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 49 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (7 lines × 2) src/batch/executors/src/executor/aggregation/orderby.rs:120— src/batch/executors/src/executor/aggregation/orderby.rs:120-126 | src/frontend/src/datafusion/aggregate/orderby.rs:121-127 — before extracting anything, compare `src/batch/executors/src/executor/aggregation/orderby.rs` and `src/frontend/src/datafusion/aggregate/orderby.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 49 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (7 lines × 2) src/batch/executors/src/executor/hash_agg.rs:364— src/batch/executors/src/executor/hash_agg.rs:364-370 | src/batch/executors/src/executor/order_by.rs:369-375 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/order_by.rs` as WHOLE FILES: this scan already matched 7 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (7 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:383— src/batch/executors/src/executor/join/hash_join.rs:383-389 | src/batch/executors/src/executor/join/hash_join.rs:410-416 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/connector_common/iceberg/jni_catalog.rs:241— src/connector/src/connector_common/iceberg/jni_catalog.rs:241-247 | src/connector/src/connector_common/iceberg/jni_catalog.rs:273-279 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/sink/clickhouse.rs:197— src/connector/src/sink/clickhouse.rs:197-203 | src/connector/src/sink/clickhouse.rs:211-217 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/sink/clickhouse.rs:238— src/connector/src/sink/clickhouse.rs:238-244 | src/connector/src/sink/clickhouse.rs:280-286 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/sink/clickhouse.rs:257— src/connector/src/sink/clickhouse.rs:257-263 | src/connector/src/sink/clickhouse.rs:299-305 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_client.rs:112— src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_client.rs:112-119 | src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_client.rs:141-147 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/sink/encoder/json.rs:397— src/connector/src/sink/encoder/json.rs:397-403 | src/connector/src/sink/encoder/json.rs:415-421 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/sink/iceberg/config.rs:192— src/connector/src/sink/iceberg/config.rs:192-198 | src/connector/src/sink/iceberg/config.rs:201-207 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/connector/src/source/reader/reader.rs:203— src/connector/src/source/reader/reader.rs:203-209 | src/connector/src/source/reader/reader.rs:230-237 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/expr/macro/src/gen.rs:1029— src/expr/macro/src/gen.rs:1029-1035 | src/expr/macro/src/gen.rs:1040-1046 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/frontend/src/binder/bind_context.rs:342— src/frontend/src/binder/bind_context.rs:342-348 | src/frontend/src/binder/bind_context.rs:350-356 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/frontend/src/binder/insert.rs:401— src/frontend/src/binder/insert.rs:401-407 | src/frontend/src/binder/insert.rs:432-438 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/frontend/src/binder/relation/watermark.rs:38— src/frontend/src/binder/relation/watermark.rs:38-44 | src/frontend/src/binder/relation/window_table_function.rs:57-63 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (7 lines × 2) src/frontend/src/catalog/system_catalog/rw_catalog/rw_schemas.rs:34— src/frontend/src/catalog/system_catalog/rw_catalog/rw_schemas.rs:34-40 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_system_tables.rs:36-42 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (7 lines × 2) src/frontend/src/optimizer/plan_node/logical_filter.rs:82— src/frontend/src/optimizer/plan_node/logical_filter.rs:82-88 | src/frontend/src/optimizer/plan_node/stream_filter.rs:62-68 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (7 lines × 2) src/frontend/src/optimizer/plan_node/logical_gap_fill.rs:221— src/frontend/src/optimizer/plan_node/logical_gap_fill.rs:221-227 | src/frontend/src/optimizer/plan_node/logical_gap_fill.rs:230-236 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/frontend/src/optimizer/plan_node/logical_kafka_scan.rs:185— src/frontend/src/optimizer/plan_node/logical_kafka_scan.rs:185-191 | src/frontend/src/optimizer/plan_node/logical_kafka_scan.rs:196-202 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/frontend/src/optimizer/plan_node/stream_exchange.rs:91— src/frontend/src/optimizer/plan_node/stream_exchange.rs:91-97 | src/frontend/src/optimizer/plan_node/stream_row_id_gen.rs:44-50 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (7 lines × 2) src/frontend/src/optimizer/plan_node/stream_group_topn.rs:145— src/frontend/src/optimizer/plan_node/stream_group_topn.rs:145-151 | src/frontend/src/optimizer/plan_node/stream_topn.rs:83-89 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (7 lines × 2) src/frontend/src/webhook/websocket.rs:483— src/frontend/src/webhook/websocket.rs:483-489 | src/frontend/src/webhook/websocket.rs:531-537 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (7 lines × 2) src/frontend/src/handler/drop_sink.rs:35— src/frontend/src/handler/drop_sink.rs:35-41 | src/frontend/src/handler/drop_subscription.rs:34-40 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (7 lines × 2) src/meta/src/controller/catalog/mod.rs:424— src/meta/src/controller/catalog/mod.rs:424-430 | src/meta/src/controller/streaming_job.rs:1743-1749 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (9 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:2089— src/batch/executors/src/executor/join/hash_join.rs:2089-2097 | src/batch/executors/src/executor/join/hash_join.rs:2139-2147 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/common/src/session_config/parallelism.rs:120— src/common/src/session_config/parallelism.rs:120-128 | src/common/src/session_config/parallelism.rs:186-194 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/compute/src/observer/observer_manager.rs:38— src/compute/src/observer/observer_manager.rs:38-46 | src/frontend/src/observer/observer_manager.rs:540-548 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (9 lines × 2) src/ctl/src/cmd_impl/profile.rs:44— src/ctl/src/cmd_impl/profile.rs:44-52 | src/ctl/src/cmd_impl/profile.rs:114-122 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/expr/core/src/expr/mod.rs:94— src/expr/core/src/expr/mod.rs:94-102 | src/expr/core/src/expr/mod.rs:132-140 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/frontend/src/binder/relation/watermark.rs:66— src/frontend/src/binder/relation/watermark.rs:66-74 | src/frontend/src/binder/relation/window_table_function.rs:86-94 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/frontend/src/binder/relation/watermark.rs:78— src/frontend/src/binder/relation/watermark.rs:78-86 | src/frontend/src/binder/relation/window_table_function.rs:111-119 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/frontend/src/expr/function_call.rs:307— src/frontend/src/expr/function_call.rs:307-315 | src/frontend/src/expr/function_call_with_lambda.rs:109-117 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/frontend/src/observer/observer_manager.rs:363— src/frontend/src/observer/observer_manager.rs:363-371 | src/frontend/src/observer/observer_manager.rs:402-410 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/frontend/src/observer/observer_manager.rs:373— src/frontend/src/observer/observer_manager.rs:373-381 | src/frontend/src/observer/observer_manager.rs:412-420 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/frontend/src/optimizer/plan_node/batch_log_seq_scan.rs:92— src/frontend/src/optimizer/plan_node/batch_log_seq_scan.rs:92-100 | src/frontend/src/optimizer/plan_node/batch_sys_seq_scan.rs:66-74 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/frontend/src/optimizer/plan_node/stream_asof_join.rs:140— src/frontend/src/optimizer/plan_node/stream_asof_join.rs:140-148 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:289-297 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` and `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (9 lines × 2) src/frontend/src/optimizer/plan_node/stream_iceberg_with_pk_index_writer.rs:129— src/frontend/src/optimizer/plan_node/stream_iceberg_with_pk_index_writer.rs:129-137 | src/frontend/src/optimizer/plan_node/stream_sink.rs:948-956 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/frontend/src/optimizer/plan_node/stream_materialize.rs:642— src/frontend/src/optimizer/plan_node/stream_materialize.rs:642-650 | src/frontend/src/optimizer/plan_node/stream_vector_index_write.rs:216-224 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/frontend/src/webhook/mod.rs:189— src/frontend/src/webhook/mod.rs:189-197 | src/frontend/src/webhook/mod.rs:207-215 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/meta/src/barrier/info.rs:1087— src/meta/src/barrier/info.rs:1087-1095 | src/meta/src/barrier/info.rs:1135-1143 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/meta/src/hummock/manager/time_travel.rs:753— src/meta/src/hummock/manager/time_travel.rs:753-761 | src/meta/src/hummock/manager/time_travel.rs:779-787 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/meta/src/stream/scale.rs:233— src/meta/src/stream/scale.rs:233-241 | src/meta/src/stream/scale.rs:293-301 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/meta/src/controller/catalog/alter_op.rs:510— src/meta/src/controller/catalog/alter_op.rs:510-518 | src/meta/src/controller/catalog/util.rs:142-150 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/risedevtool/src/bin/risedev-dev.rs:268— src/risedevtool/src/bin/risedev-dev.rs:268-276 | src/risedevtool/src/bin/risedev-dev.rs:411-419 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/risedevtool/src/bin/risedev-dev.rs:269— src/risedevtool/src/bin/risedev-dev.rs:269-277 | src/risedevtool/src/bin/risedev-dev.rs:351-359 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/risedevtool/src/task/compactor_service.rs:85— src/risedevtool/src/task/compactor_service.rs:85-93 | src/risedevtool/src/task/frontend_service.rs:98-106 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/sqlparser/src/ast/mod.rs:3081— src/sqlparser/src/ast/mod.rs:3081-3090 | src/sqlparser/src/ast/query.rs:432-440 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9 lines × 2) src/storage/src/hummock/sstable/writer.rs:287— src/storage/src/hummock/sstable/writer.rs:287-295 | src/storage/src/hummock/sstable/writer.rs:299-307 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2) src/storage/src/monitor/local_metrics.rs:549— src/storage/src/monitor/local_metrics.rs:549-557 | src/storage/src/monitor/local_metrics.rs:587-595 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
risingwave_frontend::handler::handle (cognitive 100) src/frontend/src/handler/mod.rs:306— risingwave_frontend::handler::handle has cognitive complexity 100 (threshold 15). Drivers by points: if/else 26 (56 pts), match/switch 19 (40 pts), loops 1 (3 pts), boolean chains 1 (nesting depth added 53). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::expr::type_inference::func::infer_type_for_special (cognitive 98) src/frontend/src/expr/type_inference/func.rs:323— risingwave_frontend::expr::type_inference::func::infer_type_for_special has cognitive complexity 98 (threshold 15). Drivers by points: if/else 18 (40 pts), match/switch 20 (35 pts), loops 8 (17 pts), boolean chains 6 (nesting depth added 46). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_frontend::handler::create_sink::gen_sink_plan (cognitive 95) src/frontend/src/handler/create_sink.rs:151— risingwave_frontend::handler::create_sink::gen_sink_plan has cognitive complexity 95 (threshold 15). Drivers by points: if/else 43 (75 pts), boolean chains 8, loops 3 (8 pts), match/switch 3 (4 pts) (nesting depth added 38). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::create_source::bind_all_columns (cognitive 76) src/frontend/src/handler/create_source.rs:231— risingwave_frontend::handler::create_source::bind_all_columns has cognitive complexity 76 (threshold 15). Drivers by points: if/else 20 (58 pts), loops 2 (9 pts), match/switch 3 (7 pts), boolean chains 2 (nesting depth added 49). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
risingwave_frontend::handler::handle_privilege::make_prost_privilege (cognitive 67) src/frontend/src/handler/handle_privilege.rs:46— risingwave_frontend::handler::handle_privilege::make_prost_privilege has cognitive complexity 67 (threshold 15). Drivers by points: loops 22 (45 pts), match/switch 7 (18 pts), if/else 1 (4 pts) (nesting depth added 37). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_frontend::handler::explain::do_handle_explain (cognitive 53) src/frontend/src/handler/explain.rs:49— risingwave_frontend::handler::explain::do_handle_explain has cognitive complexity 53 (threshold 15). Drivers by points: if/else 14 (28 pts), match/switch 9 (23 pts), boolean chains 2 (nesting depth added 28). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::create_index::gen_create_index_plan (cognitive 47) src/frontend/src/handler/create_index.rs:143— risingwave_frontend::handler::create_index::gen_create_index_plan has cognitive complexity 47 (threshold 15). Drivers by points: if/else 21 (26 pts), match/switch 6 (10 pts), boolean chains 7, loops 3 (4 pts) (nesting depth added 10). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
risingwave_frontend::optimizer::plan_node::logical_kafka_scan::expr_to_kafka_timestamp_range (cognitive 46) src/frontend/src/optimizer/plan_node/logical_kafka_scan.rs:129— risingwave_frontend::optimizer::plan_node::logical_kafka_scan::expr_to_kafka_timestamp_range has cognitive complexity 46 (threshold 15). Drivers by points: if/else 18 (35 pts), match/switch 6 (9 pts), boolean chains 2 (nesting depth added 20). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_frontend::datafusion::project_set::project_set_stream (cognitive 45) src/frontend/src/datafusion/project_set.rs:284— risingwave_frontend::datafusion::project_set::project_set_stream has cognitive complexity 45 (threshold 15). Drivers by points: if/else 6 (22 pts), loops 6 (16 pts), match/switch 1 (5 pts), boolean chains 2 (nesting depth added 30). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::create_source::bind_source_pk (cognitive 40) src/frontend/src/handler/create_source.rs:519— risingwave_frontend::handler::create_source::bind_source_pk has cognitive complexity 40 (threshold 15). Drivers by points: if/else 20 (34 pts), loops 1 (3 pts), boolean chains 2, match/switch 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::create_source::bind_create_source_or_table_with_connector (cognitive 39) src/frontend/src/handler/create_source.rs:885— risingwave_frontend::handler::create_source::bind_create_source_or_table_with_connector has cognitive complexity 39 (threshold 15). Drivers by points: if/else 19 (28 pts), boolean chains 5, loops 2 (4 pts), match/switch 1 (2 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::optimizer::plan_node::stream_hash_join::derive_watermark_for_hash_join (cognitive 39) src/frontend/src/optimizer/plan_node/stream_hash_join.rs:88— risingwave_frontend::optimizer::plan_node::stream_hash_join::derive_watermark_for_hash_join has cognitive complexity 39 (threshold 15). Drivers by points: if/else 13 (30 pts), boolean chains 7, loops 2 (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::create_table::create_iceberg_engine_table (cognitive 36) src/frontend/src/handler/create_table.rs:1453— risingwave_frontend::handler::create_table::create_iceberg_engine_table has cognitive complexity 36 (threshold 15). Drivers by points: if/else 13 (24 pts), match/switch 3 (11 pts), boolean chains 1 (nesting depth added 19). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::alter_table_column::handle_alter_table_column (cognitive 34) src/frontend/src/handler/alter_table_column.rs:118— risingwave_frontend::handler::alter_table_column::handle_alter_table_column has cognitive complexity 34 (threshold 15). Drivers by points: if/else 14 (24 pts), loops 2 (6 pts), boolean chains 3, match/switch 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::alter_owner::handle_alter_owner (cognitive 31) src/frontend/src/handler/alter_owner.rs:49— risingwave_frontend::handler::alter_owner::handle_alter_owner has cognitive complexity 31 (threshold 15). Drivers by points: if/else 14 (27 pts), loops 1 (3 pts), match/switch 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::webhook::websocket::try_handle_connection (cognitive 31) src/frontend/src/webhook/websocket.rs:230— risingwave_frontend::webhook::websocket::try_handle_connection has cognitive complexity 31 (threshold 15). Drivers by points: match/switch 8 (19 pts), if/else 4 (10 pts), boolean chains 1, loops 1 (nesting depth added 17). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_frontend::handler::create_source::validate::validate_compatibility (cognitive 31) src/frontend/src/handler/create_source/validate.rs:162— risingwave_frontend::handler::create_source::validate::validate_compatibility has cognitive complexity 31 (threshold 15). Drivers by points: if/else 13 (19 pts), boolean chains 8, match/switch 2 (4 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::utils::iceberg_predicate::rw_expr_to_iceberg_predicate (cognitive 31) src/frontend/src/utils/iceberg_predicate.rs:178— risingwave_frontend::utils::iceberg_predicate::rw_expr_to_iceberg_predicate has cognitive complexity 31 (threshold 15). Drivers by points: if/else 5 (15 pts), match/switch 6 (12 pts), loops 1 (4 pts) (nesting depth added 19). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_frontend::handler::alter_user::alter_prost_user_info (cognitive 27) src/frontend/src/handler/alter_user.rs:34— risingwave_frontend::handler::alter_user::alter_prost_user_info has cognitive complexity 27 (threshold 15). Drivers by points: if/else 10 (17 pts), boolean chains 7, match/switch 1 (2 pts), loops 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::utils::with_options::resolve_connection_ref_and_secret_ref (cognitive 27) src/frontend/src/utils/with_options.rs:272— risingwave_frontend::utils::with_options::resolve_connection_ref_and_secret_ref has cognitive complexity 27 (threshold 15). Drivers by points: if/else 10 (20 pts), loops 3 (5 pts), boolean chains 2 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::catalog::purify::try_purify_table_source_create_sql_ast (cognitive 26) src/frontend/src/catalog/purify.rs:53— risingwave_frontend::catalog::purify::try_purify_table_source_create_sql_ast has cognitive complexity 26 (threshold 15). Drivers by points: if/else 10 (16 pts), boolean chains 4, loops 2 (3 pts), match/switch 1 (3 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::create_source::external_schema::bind_columns_from_source_for_non_cdc (cognitive 26) src/frontend/src/handler/create_source/external_schema.rs:92— risingwave_frontend::handler::create_source::external_schema::bind_columns_from_source_for_non_cdc has cognitive complexity 26 (threshold 15). Drivers by points: if/else 12 (21 pts), boolean chains 3, match/switch 2 (nesting depth added 9). Of this number, 24 points are the body's own statements and 2 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_frontend::handler::drop_user::handle_drop_user (cognitive 24) src/frontend/src/handler/drop_user.rs:24— risingwave_frontend::handler::drop_user::handle_drop_user has cognitive complexity 24 (threshold 15). Drivers by points: if/else 9 (22 pts), boolean chains 1, match/switch 1 (nesting depth added 13). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_frontend::handler::alter_set_schema::handle_alter_set_schema (cognitive 24) src/frontend/src/handler/alter_set_schema.rs:30— risingwave_frontend::handler::alter_set_schema::handle_alter_set_schema has cognitive complexity 24 (threshold 15). Drivers by points: if/else 10 (20 pts), loops 1 (3 pts), match/switch 1 (nesting depth added 12). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_frontend::handler::cdc::parse_postgres_cdc_external_table_name (cognitive 24) src/frontend/src/handler/cdc.rs:166— risingwave_frontend::handler::cdc::parse_postgres_cdc_external_table_name has cognitive complexity 24 (threshold 15). Drivers by points: if/else 10 (19 pts), match/switch 1 (3 pts), boolean chains 1, loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (11 lines × 2) src/batch/executors/src/executor/hop_window.rs:180— src/batch/executors/src/executor/hop_window.rs:180-190 | src/stream/src/executor/hop_window.rs:142-152 — before extracting anything, compare `src/batch/executors/src/executor/hop_window.rs` and `src/stream/src/executor/hop_window.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (11 lines × 2) src/batch/executors/src/executor/join/distributed_lookup_join.rs:265— src/batch/executors/src/executor/join/distributed_lookup_join.rs:265-275 | src/batch/executors/src/executor/join/local_lookup_join.rs:476-486 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (11 lines × 2) src/batch/executors/src/executor/join/nested_loop_join.rs:293— src/batch/executors/src/executor/join/nested_loop_join.rs:293-303 | src/batch/executors/src/executor/join/nested_loop_join.rs:468-478 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/connector/src/sink/catalog/mod.rs:458— src/connector/src/sink/catalog/mod.rs:458-468 | src/connector/src/sink/mod.rs:370-380 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (11 lines × 2) src/connector/src/sink/iceberg/writer.rs:411— src/connector/src/sink/iceberg/writer.rs:411-421 | src/connector/src/sink/iceberg/writer.rs:627-637 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/connector/src/source/cdc/external/postgres.rs:443— src/connector/src/source/cdc/external/postgres.rs:443-453 | src/connector/src/source/cdc/external/postgres.rs:454-464 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/frontend/src/binder/expr/function/mod.rs:958— src/frontend/src/binder/expr/function/mod.rs:958-968 | src/frontend/src/binder/select.rs:362-372 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (11 lines × 2) src/frontend/src/expr/mod.rs:549— src/frontend/src/expr/mod.rs:549-559 | src/frontend/src/expr/mod.rs:572-582 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/frontend/src/handler/explain_analyze_stream_job.rs:224— src/frontend/src/handler/explain_analyze_stream_job.rs:224-234 | src/frontend/src/handler/explain_analyze_stream_job.rs:240-250 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/frontend/src/monitor/stats.rs:215— src/frontend/src/monitor/stats.rs:215-225 | src/meta/src/rpc/metrics.rs:1686-1696 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (11 lines × 2) src/frontend/src/optimizer/delta_join_solver.rs:344— src/frontend/src/optimizer/delta_join_solver.rs:344-354 | src/frontend/src/optimizer/delta_join_solver.rs:369-379 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/frontend/src/optimizer/plan_node/logical_project.rs:125— src/frontend/src/optimizer/plan_node/logical_project.rs:125-135 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:212-222 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/logical_project.rs` and `src/frontend/src/optimizer/plan_node/logical_project_set.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 62 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11 lines × 2) src/frontend/src/optimizer/plan_node/logical_project.rs:155— src/frontend/src/optimizer/plan_node/logical_project.rs:155-165 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:255-265 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/logical_project.rs` and `src/frontend/src/optimizer/plan_node/logical_project_set.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 62 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11 lines × 2) src/frontend/src/optimizer/plan_node/stream_asof_join.rs:212— src/frontend/src/optimizer/plan_node/stream_asof_join.rs:212-222 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:536-546 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` and `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11 lines × 2) src/frontend/src/optimizer/plan_node/stream_eowc_gap_fill.rs:177— src/frontend/src/optimizer/plan_node/stream_eowc_gap_fill.rs:177-187 | src/frontend/src/optimizer/plan_node/stream_gap_fill.rs:175-185 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/stream_eowc_gap_fill.rs` and `src/frontend/src/optimizer/plan_node/stream_gap_fill.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 33 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11 lines × 2) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:369— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:369-379 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:540-551 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:116— src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:116-126 | src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:186-196 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/frontend/src/handler/alter_set_schema.rs:56— src/frontend/src/handler/alter_set_schema.rs:56-66 | src/frontend/src/handler/alter_set_schema.rs:70-80 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/frontend/src/stream_fragmenter/rewrite/delta_join.rs:293— src/frontend/src/stream_fragmenter/rewrite/delta_join.rs:293-303 | src/frontend/src/stream_fragmenter/rewrite/delta_join.rs:305-315 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/meta/node/src/server.rs:520— src/meta/node/src/server.rs:520-530 | src/meta/node/src/server.rs:562-572 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/meta/src/controller/fragment.rs:735— src/meta/src/controller/fragment.rs:735-745 | src/meta/src/controller/fragment.rs:746-756 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/meta/src/controller/fragment.rs:1685— src/meta/src/controller/fragment.rs:1685-1695 | src/meta/src/controller/scale.rs:124-134 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (11 lines × 2) src/meta/src/hummock/manager/timer_task.rs:303— src/meta/src/hummock/manager/timer_task.rs:303-313 | src/meta/src/hummock/manager/timer_task.rs:322-332 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/risedevtool/src/task/meta_node_service.rs:151— src/risedevtool/src/task/meta_node_service.rs:151-161 | src/risedevtool/src/task/meta_node_service.rs:175-185 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11 lines × 2) src/sqlparser/src/parser.rs:2170— src/sqlparser/src/parser.rs:2170-2180 | src/sqlparser/src/parser.rs:2645-2655 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/batch/executors/src/executor/aggregation/orderby.rs:78— src/batch/executors/src/executor/aggregation/orderby.rs:78-87 | src/frontend/src/datafusion/aggregate/orderby.rs:79-88 — before extracting anything, compare `src/batch/executors/src/executor/aggregation/orderby.rs` and `src/frontend/src/datafusion/aggregate/orderby.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 49 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 2) src/batch/executors/src/executor/hash_agg.rs:436— src/batch/executors/src/executor/hash_agg.rs:436-445 | src/batch/executors/src/executor/order_by.rs:401-410 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/order_by.rs` as WHOLE FILES: this scan already matched 7 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 2) src/connector/src/sink/starrocks.rs:584— src/connector/src/sink/starrocks.rs:584-593 | src/connector/src/sink/starrocks.rs:607-616 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/expr/impl/src/scalar/jsonb_path.rs:77— src/expr/impl/src/scalar/jsonb_path.rs:77-86 | src/expr/impl/src/scalar/jsonb_path.rs:99-108 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/expr/macro/src/gen.rs:153— src/expr/macro/src/gen.rs:153-162 | src/expr/macro/src/gen.rs:1151-1160 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/expr/macro/src/gen.rs:470— src/expr/macro/src/gen.rs:470-479 | src/expr/macro/src/gen.rs:1304-1313 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/binder/for_system.rs:36— src/frontend/src/binder/for_system.rs:36-45 | src/frontend/src/binder/for_system.rs:53-62 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/generic/hop_window.rs:253— src/frontend/src/optimizer/plan_node/generic/hop_window.rs:253-262 | src/frontend/src/optimizer/plan_node/generic/hop_window.rs:275-284 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/generic/join.rs:234— src/frontend/src/optimizer/plan_node/generic/join.rs:234-243 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:356-365 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/join.rs` and `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 30 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/generic/join.rs:243— src/frontend/src/optimizer/plan_node/generic/join.rs:243-252 | src/frontend/src/optimizer/plan_node/stream_asof_join.rs:179-188 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/join.rs` and `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 31 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/generic/join.rs:332— src/frontend/src/optimizer/plan_node/generic/join.rs:332-341 | src/frontend/src/optimizer/plan_node/generic/join.rs:345-354 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/generic/join.rs:511— src/frontend/src/optimizer/plan_node/generic/join.rs:511-520 | src/frontend/src/optimizer/plan_node/generic/join.rs:534-543 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/generic/table_scan.rs:268— src/frontend/src/optimizer/plan_node/generic/table_scan.rs:268-277 | src/frontend/src/optimizer/rule/index_selection_rule.rs:192-201 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/logical_join.rs:431— src/frontend/src/optimizer/plan_node/logical_join.rs:431-440 | src/frontend/src/optimizer/plan_node/logical_join.rs:1204-1213 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/logical_union.rs:201— src/frontend/src/optimizer/plan_node/logical_union.rs:201-210 | src/frontend/src/optimizer/plan_node/logical_union.rs:275-284 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/stream_asof_join.rs:228— src/frontend/src/optimizer/plan_node/stream_asof_join.rs:228-237 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:581-590 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` and `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 2) src/frontend/src/optimizer/plan_node/stream_locality_provider.rs:198— src/frontend/src/optimizer/plan_node/stream_locality_provider.rs:198-207 | src/frontend/src/optimizer/plan_node/stream_table_scan.rs:275-284 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (10 lines × 2) src/frontend/src/utils/with_options.rs:548— src/frontend/src/utils/with_options.rs:548-557 | src/frontend/src/utils/with_options.rs:559-568 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/handler/alter_owner.rs:94— src/frontend/src/handler/alter_owner.rs:94-103 | src/frontend/src/handler/alter_owner.rs:108-117 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/frontend/src/handler/create_function.rs:187— src/frontend/src/handler/create_function.rs:187-196 | src/frontend/src/handler/create_sql_function.rs:159-168 — before extracting anything, compare `src/frontend/src/handler/create_function.rs` and `src/frontend/src/handler/create_sql_function.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 2) src/frontend/src/handler/create_aggregate.rs:138— src/frontend/src/handler/create_aggregate.rs:138-147 | src/frontend/src/handler/create_function.rs:193-202 — before extracting anything, compare `src/frontend/src/handler/create_aggregate.rs` and `src/frontend/src/handler/create_function.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 59 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 2) src/frontend/src/handler/alter_rename.rs:296— src/frontend/src/handler/alter_rename.rs:296-305 | src/frontend/src/handler/drop_database.rs:62-71 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (10 lines × 2) src/meta/src/barrier/backfill_order_control.rs:68— src/meta/src/barrier/backfill_order_control.rs:68-77 | src/meta/src/barrier/backfill_order_control.rs:136-145 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/meta/src/barrier/checkpoint/state.rs:471— src/meta/src/barrier/checkpoint/state.rs:471-480 | src/meta/src/barrier/checkpoint/state.rs:1250-1259 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 2) src/meta/src/barrier/edge_builder.rs:539— src/meta/src/barrier/edge_builder.rs:539-548 | src/meta/src/barrier/edge_builder.rs:578-587 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/batch/executors/src/executor/iceberg_scan.rs:186— src/batch/executors/src/executor/iceberg_scan.rs:186-191 | src/batch/executors/src/executor/source.rs:98-103 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (6 lines × 2) src/common/heap_profiling/src/profile_service.rs:128— src/common/heap_profiling/src/profile_service.rs:128-133 | src/common/heap_profiling/src/profile_service.rs:141-146 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/connector/src/connector_common/iceberg/jni_catalog.rs:317— src/connector/src/connector_common/iceberg/jni_catalog.rs:317-322 | src/connector/src/connector_common/iceberg/jni_catalog.rs:375-380 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/connector/src/parser/unified/debezium.rs:1361— src/connector/src/parser/unified/debezium.rs:1361-1366 | src/connector/src/parser/unified/debezium.rs:1396-1401 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/connector/src/source/pulsar/source/reader.rs:406— src/connector/src/source/pulsar/source/reader.rs:406-411 | src/connector/src/source/pulsar/source/reader.rs:446-451 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/expr/core/src/expr/expr_udf.rs:62— src/expr/core/src/expr/expr_udf.rs:62-67 | src/expr/core/src/table_function/user_defined.rs:52-57 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (6 lines × 2) src/expr/macro/src/lib.rs:427— src/expr/macro/src/lib.rs:427-432 | src/expr/macro/src/lib.rs:455-460 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/expr/macro/src/lib.rs:473— src/expr/macro/src/lib.rs:473-478 | src/expr/macro/src/lib.rs:491-496 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/expr/macro/src/gen.rs:342— src/expr/macro/src/gen.rs:342-347 | src/expr/macro/src/gen.rs:352-357 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/expr/macro/src/gen.rs:777— src/expr/macro/src/gen.rs:777-783 | src/expr/macro/src/gen.rs:1146-1151 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/frontend/src/expr/table_function.rs:187— src/frontend/src/expr/table_function.rs:187-192 | src/frontend/src/optimizer/rule/table_function_to_file_scan_rule.rs:72-77 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (6 lines × 2) src/frontend/src/optimizer/plan_node/stream_simple_agg.rs:121— src/frontend/src/optimizer/plan_node/stream_simple_agg.rs:121-126 | src/frontend/src/optimizer/plan_node/stream_stateless_simple_agg.rs:95-100 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (6 lines × 2) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:611— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:611-616 | src/frontend/src/optimizer/rule/index_selection_rule.rs:739-744 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (6 lines × 2) src/frontend/src/scheduler/distributed/stage.rs:407— src/frontend/src/scheduler/distributed/stage.rs:407-416 | src/frontend/src/scheduler/distributed/stage.rs:434-439 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/jni_core/src/lib.rs:1104— src/jni_core/src/lib.rs:1104-1109 | src/jni_core/src/lib.rs:1228-1233 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/meta/src/manager/diagnose.rs:169— src/meta/src/manager/diagnose.rs:169-174 | src/meta/src/manager/diagnose.rs:969-974 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/meta/src/controller/catalog/util.rs:100— src/meta/src/controller/catalog/util.rs:100-105 | src/meta/src/controller/catalog/util.rs:321-326 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/sqlparser/src/parser.rs:5784— src/sqlparser/src/parser.rs:5784-5790 | src/sqlparser/src/parser.rs:6840-6845 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/storage/src/mem_table.rs:265— src/storage/src/mem_table.rs:265-270 | src/storage/src/mem_table.rs:331-336 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/stream/src/executor/dynamic_filter.rs:238— src/stream/src/executor/dynamic_filter.rs:238-243 | src/stream/src/executor/dynamic_filter.rs:247-252 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/stream/src/executor/top_n/group_top_n.rs:202— src/stream/src/executor/top_n/group_top_n.rs:202-207 | src/stream/src/executor/top_n/group_top_n_appendonly.rs:185-190 — before extracting anything, compare `src/stream/src/executor/top_n/group_top_n.rs` and `src/stream/src/executor/top_n/group_top_n_appendonly.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 69 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (6 lines × 2) src/stream/src/executor/over_window/frame_finder.rs:414— src/stream/src/executor/over_window/frame_finder.rs:414-419 | src/stream/src/executor/over_window/frame_finder.rs:434-439 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 2) src/batch/executors/src/executor/project_set.rs:208— src/batch/executors/src/executor/project_set.rs:208-213 | src/stream/src/executor/project/project_set.rs:362-367 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (6 lines × 2) src/common/src/array/num256_array.rs:133— src/common/src/array/num256_array.rs:133-138 | src/common/src/array/primitive_array.rs:304-309 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (6 lines × 2) src/connector/src/sink/snowflake_redshift/redshift.rs:357— src/connector/src/sink/snowflake_redshift/redshift.rs:357-362 | src/connector/src/sink/snowflake_redshift/snowflake.rs:628-633 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Change coupling: simd_json_parser.rs ↔ simd_json_parser.rs src/connector/src/parser/debezium/simd_json_parser.rs— `src/connector/src/parser/debezium/simd_json_parser.rs` and `src/connector/src/parser/maxwell/simd_json_parser.rs` change together 88% of the time (14 of the 16 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 14 shared commits counted here, the most recent 3 are `af8aee94` fix(mysql-cdc): up cast all unsigned int types (#23278); `755c8202` feat(cdc): allow user config `debezium.time.precision.mode` to handle…; `9b5bcdc3` refactor(source): cleanup unused `ParserProperties::key_encoding_conf… — run `git show` on any of them.
Change coupling: stream_project.rs ↔ stream_project_set.rs src/frontend/src/optimizer/plan_node/stream_project.rs— `src/frontend/src/optimizer/plan_node/stream_project.rs` and `src/frontend/src/optimizer/plan_node/stream_project_set.rs` change together 83% of the time (10 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 10 shared commits counted here, the most recent 3 are `ef3e9e6e` fix(planner): reject impure expressions on retract stream on `to_prot…; `dc3a3fc1` refactor(optimizer): some clean up for stream nodes' constructors (#1…; `96498a4b` refactor(optimizer): unify watermark derivation and monotonicity deri… — run `git show` on any of them.
Change coupling: stream_hash_agg.rs ↔ stream_simple_agg.rs src/frontend/src/optimizer/plan_node/stream_hash_agg.rs— `src/frontend/src/optimizer/plan_node/stream_hash_agg.rs` and `src/frontend/src/optimizer/plan_node/stream_simple_agg.rs` change together 82% of the time (14 of the 17 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 14 shared commits counted here, the most recent 3 are `ef3e9e6e` fix(planner): reject impure expressions on retract stream on `to_prot…; `3abd4da1` refactor(optimizer): introduce `Upsert` stream kind & reject it in ma…; `3ee72eb1` refactor(proto): add `LATEST` const value for proto message version e… — run `git show` on any of them.
Change coupling: create_sink.rs ↔ drop_sink.rs src/frontend/src/handler/create_sink.rs— `src/frontend/src/handler/create_sink.rs` and `src/frontend/src/handler/drop_sink.rs` change together 80% of the time (12 of the 15 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 12 shared commits counted here, the most recent 3 are `92b1757b` feat(frontend): improve notifications for slow DDL (CREATE TABLE and …; `f8414794` feat: manage all catalogs of the iceberg table in a transactional man…; `db6887f4` refactor(meta): deprecate incoming sinks fields in Table (#23091) — run `git show` on any of them.
Change coupling: stream_group_topn.rs ↔ stream_topn.rs src/frontend/src/optimizer/plan_node/stream_group_topn.rs— `src/frontend/src/optimizer/plan_node/stream_group_topn.rs` and `src/frontend/src/optimizer/plan_node/stream_topn.rs` change together 79% of the time (11 of the 14 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 11 shared commits counted here, the most recent 3 are `62e18582` feat(stream): forward watermarks through TopN executors (#27056); `3abd4da1` refactor(optimizer): introduce `Upsert` stream kind & reject it in ma…; `a1f114c0` fix(stream topn): fix pk indices of `TopN` and `GroupTopN` (#12840) — run `git show` on any of them.
Change coupling: stream_simple_agg.rs ↔ stream_stateless_simple_agg.rs src/frontend/src/optimizer/plan_node/stream_simple_agg.rs— `src/frontend/src/optimizer/plan_node/stream_simple_agg.rs` and `src/frontend/src/optimizer/plan_node/stream_stateless_simple_agg.rs` change together 79% of the time (11 of the 14 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 11 shared commits counted here, the most recent 3 are `ef3e9e6e` fix(planner): reject impure expressions on retract stream on `to_prot…; `3abd4da1` refactor(optimizer): introduce `Upsert` stream kind & reject it in ma…; `4d629b76` fix(optimizer): let it panic when calling `dist_column_indices` on `S… — run `git show` on any of them.
Change coupling: stream_hash_agg.rs ↔ stream_stateless_simple_agg.rs src/frontend/src/optimizer/plan_node/stream_hash_agg.rs— `src/frontend/src/optimizer/plan_node/stream_hash_agg.rs` and `src/frontend/src/optimizer/plan_node/stream_stateless_simple_agg.rs` change together 79% of the time (11 of the 14 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 11 shared commits counted here, the most recent 3 are `ef3e9e6e` fix(planner): reject impure expressions on retract stream on `to_prot…; `3abd4da1` refactor(optimizer): introduce `Upsert` stream kind & reject it in ma…; `ac0bb234` fix(stream agg): fix agg backwards compatibility issue introduced by … — run `git show` on any of them.
Change coupling: json_parser.rs ↔ simd_json_parser.rs src/connector/src/parser/json_parser.rs— `src/connector/src/parser/json_parser.rs` and `src/connector/src/parser/maxwell/simd_json_parser.rs` change together 75% of the time (12 of the 16 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 12 shared commits counted here, the most recent 3 are `af175db5` feat(source): `encode json` option `timestamptz.handling.mode` (#16265); `61ab2cd6` feat(source): support json schema (#11797); `cf0940c6` refactor(connector): avoid using macro in parser (#10120) — run `git show` on any of them.
Change coupling: fs_fetch.rs ↔ trad_source.rs src/stream/src/from_proto/source/fs_fetch.rs— `src/stream/src/from_proto/source/fs_fetch.rs` and `src/stream/src/from_proto/source/trad_source.rs` change together 75% of the time (9 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 9 shared commits counted here, the most recent 3 are `21f60ba1` fix(source): complete S3/GCS FULL_RELOAD refresh (#26016); `3572992f` refactor: make batch posix source follow new stream plan (#23504); `ff495144` fix: deprecate `SinkPayloadFormat` (#16723) — run `git show` on any of them.
Change coupling: tests.rs ↔ stream_manager.rs src/stream/src/task/barrier_worker/tests.rs— `src/stream/src/task/barrier_worker/tests.rs` and `src/stream/src/task/stream_manager.rs` change together 74% of the time (14 of the 19 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 14 shared commits counted here, the most recent 3 are `9e06d990` refactor(stream): reorg types and add docs for BarrierWorker and stuf…; `3b3a1c5f` refactor(barrier): explicitly maintain database barrier state separat… (at that commit the file was still `src/stream/src/task/barrier_manager/tests.rs`); `a3c6e48c` refactor: unify to subscribe mutation via barrier sender (#18255) (at that commit the file was still `src/stream/src/task/barrier_manager/tests.rs`) — run `git show` on any of them.
Change coupling: replay_impl.rs ↔ monitored_store.rs src/storage/hummock_test/src/bin/replay/replay_impl.rs— `src/storage/hummock_test/src/bin/replay/replay_impl.rs` and `src/storage/src/monitor/monitored_store.rs` change together 73% of the time (8 of the 11 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `3729ba81` refactor(storage): remove is_dirty method from state store and refine…; `13838cae` refactor(storage): unify state store trait get method (#20175); `ec899adc` refactor(storage): create new read snapshot to read for StateStore tr… — run `git show` on any of them.
Change coupling: expr_udf.rs ↔ user_defined.rs src/expr/core/src/expr/expr_udf.rs— `src/expr/core/src/expr/expr_udf.rs` and `src/expr/core/src/table_function/user_defined.rs` change together 72% of the time (13 of the 18 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 13 shared commits counted here, the most recent 3 are `0cc54b3f` feat(udf): introduce async and batched JavaScript UDF (#20403); `94154c03` refactor(udf): remove `function_type` field previously used by Deno U…; `ff02b76c` fix(udf): add `embedded-python-udf` feature and fix dockerfile (#15328) — run `git show` on any of them.
Change coupling: hash_agg.rs ↔ simple_agg.rs src/stream/src/from_proto/hash_agg.rs— `src/stream/src/from_proto/hash_agg.rs` and `src/stream/src/from_proto/simple_agg.rs` change together 70% of the time (7 of the 10 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 7 shared commits counted here, the most recent 3 are `6f25c038` fix(hash agg): split `AggGroup` inter states and outputs change build…; `96bca4ce` refactor(streaming): clean up unnecessary `metrics` field in agg exec…; `4726cdd3` fix(stream agg): use executor schema derived by optimizer instead of … — run `git show` on any of them.
Change coupling: managed_state.rs ↔ tests.rs src/stream/src/task/barrier_worker/managed_state.rs— `src/stream/src/task/barrier_worker/managed_state.rs` and `src/stream/src/task/barrier_worker/tests.rs` change together 63% of the time (12 of the 19 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 12 shared commits counted here, the most recent 3 are `73387f59` fix(meta): fence stale exchange requests across database recovery (#2…; `9e06d990` refactor(stream): reorg types and add docs for BarrierWorker and stuf…; `3b3a1c5f` refactor(barrier): explicitly maintain database barrier state separat… (at that commit the files were still `src/stream/src/task/barrier_manager/managed_state.rs` and `src/stream/src/task/barrier_manager/tests.rs`) — run `git show` on any of them.
Change coupling: chain.rs ↔ values.rs src/stream/src/executor/chain.rs— `src/stream/src/executor/chain.rs` and `src/stream/src/executor/values.rs` change together 62% of the time (8 of the 13 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `438ab534` feat(ddl): Make UpstreamSinkUnion node dynamically handle upstreams (…; `0c8b4c34` refactor(stream): store shared context in local barrier manager (#21257); `29d2e1ef` refactor: track progress minor refactor (#18446) — run `git show` on any of them.
Change coupling: FragmentGraph.tsx ↔ relation_graph.tsx dashboard/components/FragmentGraph.tsx— `dashboard/components/FragmentGraph.tsx` and `dashboard/pages/relation_graph.tsx` change together 62% of the time (8 of the 13 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 8 shared commits counted here, the most recent 3 are `59dccd3d` feat(dashboard): add Prometheus-based streaming stats with backpressu…; `ada38dc0` feat(dashboard): add throughput (rows/s) metrics (#19972); `ad95d102` feat(dashboard): improve relation & fragment graph (#19872) — run `git show` on any of them.
Change coupling: alter_table_with_sr.rs ↔ create_table.rs src/frontend/src/handler/alter_table_with_sr.rs— `src/frontend/src/handler/alter_table_with_sr.rs` and `src/frontend/src/handler/create_table.rs` change together 58% of the time (7 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 7 shared commits counted here, the most recent 3 are `b5e216c4` feat: enable clippy lints for stack overflow detection & fix warnings…; `1211b82d` refactor(frontend): defer converting into `PbTable` or `PbSource` unt…; `f0db87be` feat(frontend): use purified definition for replacing table (#20131) — run `git show` on any of them.
Change coupling: apply_agg_transpose_rule.rs ↔ distinct_agg_rule.rs src/frontend/src/optimizer/rule/apply_agg_transpose_rule.rs— `src/frontend/src/optimizer/rule/apply_agg_transpose_rule.rs` and `src/frontend/src/optimizer/rule/distinct_agg_rule.rs` change together 58% of the time (7 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 7 shared commits counted here, the most recent 3 are `6834de8b` feat(frontend): add stateless two-phase `ApproxPercentile` (#17469); `95956671` feat: disable some two phase agg (#12185); `f9025d1b` feat(frontend): support grouping sets (#10807) — run `git show` on any of them.
Change coupling: alter_table_with_sr.rs ↔ create_sink.rs src/frontend/src/handler/alter_table_with_sr.rs— `src/frontend/src/handler/alter_table_with_sr.rs` and `src/frontend/src/handler/create_sink.rs` change together 58% of the time (7 of the 12 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 7 shared commits counted here, the most recent 3 are `db6887f4` refactor(meta): deprecate incoming sinks fields in Table (#23091); `1211b82d` refactor(frontend): defer converting into `PbTable` or `PbSource` unt…; `b7d763ac` refactor: remove `col_index_mapping` when replacing table (#21685) — run `git show` on any of them.
Change coupling: status.rs ↔ rpc.rs src/meta/src/barrier/checkpoint/independent_job/creating_job/status.rs— `src/meta/src/barrier/checkpoint/independent_job/creating_job/status.rs` and `src/meta/src/barrier/rpc.rs` change together 58% of the time (11 of the 19 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 11 shared commits counted here, the most recent 3 are `06415d7f` refactor(meta): unify independent job reset handling (#26806); `96134b19` refactor(meta): extract independent ckpt job enum (#25249); `5a4cfd61` fix(snapshot-backfill): fix snapshot backfill recovery panic (#24245) (at that commit the file was still `src/meta/src/barrier/checkpoint/creating_job/status.rs`) — run `git show` on any of them.
Change coupling: config.rs ↔ risedev_env.rs src/risedevtool/src/config.rs— `src/risedevtool/src/config.rs` and `src/risedevtool/src/risedev_env.rs` change together 57% of the time (12 of the 21 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency between them. They sit in the same directory, but in this ecosystem each file is its own module — a sibling reference still needs an import — so the missing import edge is real: the coupling runs through shared behaviour, not a declared dependency. If they duplicate structure, extract the common part into one unit; otherwise the coupling is hidden and worth breaking. You can check this without leaving the row: of the 12 shared commits counted here, the most recent 3 are `7e5b5f5f` feat(risedev): support Docker-backed clickhouse sink tests (#26653); `f6d53aeb` test(iceberg): add Glue catalog e2e coverage (#26167); `8248ed52` feat(risedev): add local search and document backends (#25434) — run `git show` on any of them.
Change coupling: stage.rs ↔ local.rs src/frontend/src/scheduler/distributed/stage.rs— `src/frontend/src/scheduler/distributed/stage.rs` and `src/frontend/src/scheduler/local.rs` change together 57% of the time (26 of the 46 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 26 shared commits counted here, the most recent 3 are `7eda10ef` fix(batch): cap masked fragment mapping parallelism (#26560); `ee473f1a` refactor(frontend): per convention PlanNodeType enum (#22792); `ba76431f` feat(batch): add `batch_expr_strict_mode` to ignore expression error … — run `git show` on any of them.
Change coupling: opts.rs ↔ local_hummock_storage.rs src/storage/hummock_trace/src/opts.rs— `src/storage/hummock_trace/src/opts.rs` and `src/storage/src/hummock/store/local_hummock_storage.rs` change together 56% of the time (9 of the 16 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 9 shared commits counted here, the most recent 3 are `f6628e44` feat(observability): add fragment-level immutable memtable memory met…; `053e1e61` feat(storage): batch add flushed imm to uploader (#22342); `3a244ecd` feat: ensure each storage read only involves one vnode (#15289) — run `git show` on any of them.
Change coupling: test_utils.rs ↔ opts.rs src/storage/src/hummock/iterator/test_utils.rs— `src/storage/src/hummock/iterator/test_utils.rs` and `src/storage/src/opts.rs` change together 56% of the time (9 of the 16 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 9 shared commits counted here, the most recent 3 are `cd1686d2` fix: fix sstable serde to avoid losing bloom filter (#24025); `6a70b106` feat(storage): support hummock FLAT index (#21820); `7fa1dfff` refactor(cache): upgrade foyer to 0.12 and related deps (#18822) — run `git show` on any of them.
Change coupling: cast.rs ↔ literal.rs src/expr/impl/src/scalar/cast.rs— `src/expr/impl/src/scalar/cast.rs` and `src/frontend/src/expr/literal.rs` change together 54% of the time (7 of the 13 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well, and counted over this repository's 10,000 most recent commits rather than its whole history — a repo-wide or module-wide sweep is evidence about the sweep rather than about any pair inside it and is left out of BOTH sides of this ratio, while a dependency bump, a formatter/rename sweep, or a commit whose edit to one of the two files was a tool directive such as //go:generate or whitespace only is left out of the shared count ONLY, so the two sides are not taken over identical commit sets) with no explicit dependency — the edge is real but nothing declares it. Read the pair before acting: if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE — the registration is the link, and it is meant not to be an import — and the thing to add is a comment on each side naming the other, not a merge; if they simply belong together, co-locate them; if neither holds, the coupling is hidden and worth breaking. You can check this without leaving the row: of the 7 shared commits counted here, the most recent 3 are `deff9bee` feat(common): support input/output of new data type `vector(n)` (#22019); `e1de1857` feat: support `map_access` (#17986); `cd710527` fix(binder): distinguish `'a'::varchar` from untyped `'a'` (#10140) (at that commit the file was still `src/expr/src/vector_op/cast.rs`) — run `git show` on any of them.
Duplicated block (13 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:503— src/batch/executors/src/executor/join/hash_join.rs:503-515 | src/batch/executors/src/executor/order_by.rs:134-146 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (13 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:742— src/batch/executors/src/executor/join/hash_join.rs:742-754 | src/batch/executors/src/executor/join/lookup_join_base.rs:212-224 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (13 lines × 2) src/batch/executors/src/executor/join/nested_loop_join.rs:311— src/batch/executors/src/executor/join/nested_loop_join.rs:311-323 | src/batch/executors/src/executor/join/nested_loop_join.rs:499-511 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/batch/executors/src/executor/join/nested_loop_join.rs:381— src/batch/executors/src/executor/join/nested_loop_join.rs:381-393 | src/batch/executors/src/executor/join/nested_loop_join.rs:425-437 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/common/src/types/to_binary.rs:104— src/common/src/types/to_binary.rs:104-116 | src/common/src/types/to_binary.rs:127-139 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_config.rs:258— src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_config.rs:258-270 | src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_config.rs:272-284 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/connector/src/source/cdc/external/postgres.rs:403— src/connector/src/source/cdc/external/postgres.rs:403-415 | src/connector/src/source/cdc/external/postgres.rs:694-706 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:100— src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:100-112 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_files.rs:92-104 — before extracting anything, compare `src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs` and `src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_files.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 41 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (13 lines × 2) src/frontend/src/metrics_reader.rs:126— src/frontend/src/metrics_reader.rs:126-138 | src/meta/src/dashboard/mod.rs:897-909 — before extracting anything, compare `src/frontend/src/metrics_reader.rs` and `src/meta/src/dashboard/mod.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 42 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (13 lines × 2) src/frontend/src/optimizer/plan_node/stream_cdc_table_scan.rs:166— src/frontend/src/optimizer/plan_node/stream_cdc_table_scan.rs:166-178 | src/frontend/src/optimizer/plan_node/stream_source_scan.rs:108-120 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (13 lines × 2) src/frontend/src/optimizer/plan_node/stream_eowc_gap_fill.rs:150— src/frontend/src/optimizer/plan_node/stream_eowc_gap_fill.rs:150-162 | src/frontend/src/optimizer/plan_node/stream_gap_fill.rs:143-155 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/stream_eowc_gap_fill.rs` and `src/frontend/src/optimizer/plan_node/stream_gap_fill.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 33 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (13 lines × 2) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:350— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:350-362 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:510-522 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/frontend/src/optimizer/rule/except_to_anti_join_rule.rs:26— src/frontend/src/optimizer/rule/except_to_anti_join_rule.rs:26-38 | src/frontend/src/optimizer/rule/intersect_to_semi_join_rule.rs:28-40 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (13 lines × 2) src/java_binding/src/lib.rs:56— src/java_binding/src/lib.rs:56-68 | src/jni_core/src/jvm_runtime.rs:161-173 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (13 lines × 2) src/meta/model/migration/src/m20240820_081248_add_time_travel_per_table_epoch.rs:14— src/meta/model/migration/src/m20240820_081248_add_time_travel_per_table_epoch.rs:14-26 | src/meta/model/migration/src/m20240820_081248_add_time_travel_per_table_epoch.rs:33-45 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/meta/service/src/ddl_service.rs:1579— src/meta/service/src/ddl_service.rs:1579-1591 | src/meta/service/src/ddl_service.rs:1602-1614 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/meta/src/controller/streaming_job.rs:596— src/meta/src/controller/streaming_job.rs:596-608 | src/meta/src/controller/streaming_job.rs:769-781 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/meta/src/controller/streaming_job.rs:1403— src/meta/src/controller/streaming_job.rs:1403-1415 | src/meta/src/controller/streaming_job.rs:2451-2463 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/meta/src/controller/streaming_job.rs:3353— src/meta/src/controller/streaming_job.rs:3353-3365 | src/meta/src/controller/streaming_job.rs:3400-3412 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/sqlparser/src/parser.rs:2895— src/sqlparser/src/parser.rs:2895-2907 | src/sqlparser/src/parser.rs:3010-3022 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/storage/src/hummock/store/local_hummock_storage.rs:848— src/storage/src/hummock/store/local_hummock_storage.rs:848-860 | src/storage/src/hummock/store/local_hummock_storage.rs:930-942 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/stream/src/executor/asof_join.rs:233— src/stream/src/executor/asof_join.rs:233-245 | src/stream/src/executor/hash_join.rs:402-414 — before extracting anything, compare `src/stream/src/executor/asof_join.rs` and `src/stream/src/executor/hash_join.rs` as WHOLE FILES: this scan already matched 13 separate duplicated blocks between them, totalling at least 244 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (13 lines × 2) src/stream/src/executor/backfill/cdc/upstream_table/snapshot.rs:181— src/stream/src/executor/backfill/cdc/upstream_table/snapshot.rs:181-193 | src/stream/src/executor/backfill/cdc/upstream_table/snapshot.rs:275-287 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/stream/src/executor/over_window/range_cache.rs:233— src/stream/src/executor/over_window/range_cache.rs:233-245 | src/stream/src/executor/over_window/range_cache.rs:279-291 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 2) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_fetch.rs:167— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_fetch.rs:167-179 | src/stream/src/executor/source/batch_source/batch_iceberg_fetch.rs:344-356 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 2) src/connector/src/sink/doris_starrocks_connector.rs:245— src/connector/src/sink/doris_starrocks_connector.rs:245-249 | src/connector/src/sink/doris_starrocks_connector.rs:505-509 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/connector/src/sink/snowflake_redshift/redshift.rs:726— src/connector/src/sink/snowflake_redshift/redshift.rs:726-730 | src/connector/src/sink/snowflake_redshift/redshift.rs:763-767 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/expr/core/src/aggregate/def.rs:183— src/expr/core/src/aggregate/def.rs:183-187 | src/expr/core/src/aggregate/def.rs:202-206 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:212— src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:212-216 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:231-235 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/frontend/src/expr/utils.rs:342— src/frontend/src/expr/utils.rs:342-346 | src/frontend/src/expr/utils.rs:355-359 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/frontend/src/observer/observer_manager.rs:260— src/frontend/src/observer/observer_manager.rs:260-264 | src/frontend/src/observer/observer_manager.rs:281-285 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/frontend/src/optimizer/plan_node/batch_hash_join.rs:237— src/frontend/src/optimizer/plan_node/batch_hash_join.rs:237-241 | src/frontend/src/optimizer/plan_node/batch_nested_loop_join.rs:128-132 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 2) src/frontend/src/optimizer/plan_node/batch_log_seq_scan.rs:90— src/frontend/src/optimizer/plan_node/batch_log_seq_scan.rs:90-94 | src/frontend/src/optimizer/plan_node/stream_cdc_table_scan.rs:131-135 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 2) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:257— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:257-261 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:343-347 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:389— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:389-393 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:560-564 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/meta/src/hummock/compaction/picker/manual_compaction_picker.rs:302— src/meta/src/hummock/compaction/picker/manual_compaction_picker.rs:302-307 | src/meta/src/hummock/compaction/picker/min_overlap_compaction_picker.rs:152-156 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 2) src/meta/src/controller/catalog/util.rs:649— src/meta/src/controller/catalog/util.rs:649-653 | src/meta/src/controller/catalog/util.rs:659-663 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/object_store/src/object/mem.rs:232— src/object_store/src/object/mem.rs:232-236 | src/object_store/src/object/sim/mod.rs:102-106 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (5 lines × 2) src/sqlparser/src/parser.rs:2484— src/sqlparser/src/parser.rs:2484-2488 | src/sqlparser/src/parser.rs:2503-2507 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/storage/hummock_sdk/src/key.rs:242— src/storage/hummock_sdk/src/key.rs:242-246 | src/storage/hummock_sdk/src/key.rs:273-277 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/storage/src/hummock/compactor/compaction_utils.rs:302— src/storage/src/hummock/compactor/compaction_utils.rs:302-306 | src/storage/src/hummock/compactor/shared_buffer_compact.rs:380-384 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 2) src/stream/src/common/table/state_table.rs:1309— src/stream/src/common/table/state_table.rs:1309-1313 | src/stream/src/common/table/state_table.rs:1366-1370 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/stream/src/executor/approx_percentile/local.rs:69— src/stream/src/executor/approx_percentile/local.rs:69-73 | src/stream/src/executor/approx_percentile/local.rs:76-80 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/stream/src/executor/backfill/utils.rs:139— src/stream/src/executor/backfill/utils.rs:139-143 | src/stream/src/executor/backfill/utils.rs:150-154 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/stream/src/executor/iceberg_with_pk_index/compaction_resolver.rs:411— src/stream/src/executor/iceberg_with_pk_index/compaction_resolver.rs:411-415 | src/stream/src/executor/iceberg_with_pk_index/compaction_resolver.rs:456-460 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/stream/src/executor/iceberg_with_pk_index/compaction_resolver.rs:426— src/stream/src/executor/iceberg_with_pk_index/compaction_resolver.rs:426-430 | src/stream/src/executor/iceberg_with_pk_index/compaction_resolver.rs:472-476 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5 lines × 2) src/batch/executors/src/executor/hash_agg.rs:462— src/batch/executors/src/executor/hash_agg.rs:462-466 | src/batch/executors/src/executor/order_by.rs:418-422 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/order_by.rs` as WHOLE FILES: this scan already matched 7 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (5 lines × 2) src/frontend/src/catalog/source_catalog.rs:130— src/frontend/src/catalog/source_catalog.rs:130-134 | src/frontend/src/catalog/table_catalog.rs:293-297 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 2) src/storage/src/hummock/sstable/backward_sstable_iterator.rs:190— src/storage/src/hummock/sstable/backward_sstable_iterator.rs:190-194 | src/storage/src/hummock/sstable/forward_sstable_iterator.rs:321-325 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 2) src/stream/src/executor/aggregate/hash_agg.rs:131— src/stream/src/executor/aggregate/hash_agg.rs:131-135 | src/stream/src/executor/aggregate/simple_agg.rs:93-97 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (12 lines × 2) src/batch/executors/src/executor/aggregation/orderby.rs:136— src/batch/executors/src/executor/aggregation/orderby.rs:136-147 | src/frontend/src/datafusion/aggregate/orderby.rs:137-148 — before extracting anything, compare `src/batch/executors/src/executor/aggregation/orderby.rs` and `src/frontend/src/datafusion/aggregate/orderby.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 49 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (12 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:1255— src/batch/executors/src/executor/join/hash_join.rs:1255-1266 | src/batch/executors/src/executor/join/hash_join.rs:1504-1515 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/common/src/util/scan_range.rs:147— src/common/src/util/scan_range.rs:147-158 | src/common/src/util/scan_range.rs:199-210 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/connector/src/sink/dynamodb.rs:166— src/connector/src/sink/dynamodb.rs:166-177 | src/connector/src/sink/dynamodb.rs:262-273 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/expr/impl/src/scalar/jsonb_delete.rs:315— src/expr/impl/src/scalar/jsonb_delete.rs:315-326 | src/expr/impl/src/scalar/jsonb_delete.rs:348-359 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/frontend/src/expr/mod.rs:712— src/frontend/src/expr/mod.rs:712-723 | src/frontend/src/expr/mod.rs:728-739 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/frontend/src/optimizer/plan_node/generic/join.rs:230— src/frontend/src/optimizer/plan_node/generic/join.rs:230-241 | src/frontend/src/optimizer/plan_node/stream_asof_join.rs:165-176 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/join.rs` and `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 31 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (12 lines × 2) src/frontend/src/optimizer/plan_node/logical_project.rs:415— src/frontend/src/optimizer/plan_node/logical_project.rs:415-426 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:446-457 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/logical_project.rs` and `src/frontend/src/optimizer/plan_node/logical_project_set.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 62 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (12 lines × 2) src/frontend/src/optimizer/plan_node/utils.rs:384— src/frontend/src/optimizer/plan_node/utils.rs:384-395 | src/frontend/src/optimizer/plan_node/utils.rs:435-446 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/frontend/src/handler/create_database.rs:71— src/frontend/src/handler/create_database.rs:71-82 | src/frontend/src/handler/create_schema.rs:65-76 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (12 lines × 2) src/frontend/src/binder/expr/function/mod.rs:304— src/frontend/src/binder/expr/function/mod.rs:304-315 | src/frontend/src/binder/expr/function/mod.rs:354-365 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/jni_core/src/lib.rs:1209— src/jni_core/src/lib.rs:1209-1220 | src/jni_core/src/lib.rs:1284-1295 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/meta/service/src/ddl_service.rs:1934— src/meta/service/src/ddl_service.rs:1934-1945 | src/meta/service/src/ddl_service.rs:1984-1995 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/sqlparser/src/ast/mod.rs:729— src/sqlparser/src/ast/mod.rs:729-740 | src/sqlparser/src/ast/mod.rs:743-754 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/storage/src/monitor/traced_store.rs:190— src/storage/src/monitor/traced_store.rs:190-201 | src/storage/src/monitor/traced_store.rs:210-221 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/storage/src/monitor/traced_store.rs:374— src/storage/src/monitor/traced_store.rs:374-385 | src/storage/src/monitor/traced_store.rs:394-405 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/stream/src/common/log_store_impl/kv_log_store/serde.rs:653— src/stream/src/common/log_store_impl/kv_log_store/serde.rs:653-664 | src/stream/src/common/log_store_impl/kv_log_store/serde.rs:684-695 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/stream/src/common/table/state_table.rs:2009— src/stream/src/common/table/state_table.rs:2009-2020 | src/stream/src/common/table/state_table.rs:2098-2109 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/stream/src/executor/aggregate/agg_group.rs:478— src/stream/src/executor/aggregate/agg_group.rs:478-489 | src/stream/src/executor/aggregate/agg_group.rs:552-563 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/stream/src/executor/aggregate/hash_agg.rs:463— src/stream/src/executor/aggregate/hash_agg.rs:463-474 | src/stream/src/executor/aggregate/hash_agg.rs:480-491 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/stream/src/executor/join/asof_join.rs:399— src/stream/src/executor/join/asof_join.rs:399-410 | src/stream/src/executor/join/asof_join.rs:425-436 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) REDACTED:676— REDACTED:676-687 | REDACTED:708-719 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/stream/src/executor/over_window/range_cache.rs:247— src/stream/src/executor/over_window/range_cache.rs:247-258 | src/stream/src/executor/over_window/range_cache.rs:294-305 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 2) src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:229— src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:229-240 | src/stream/src/executor/source/source_executor.rs:856-867 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (12 lines × 2) src/stream/src/executor/source/fs_fetch_executor.rs:423— src/stream/src/executor/source/fs_fetch_executor.rs:423-434 | src/stream/src/executor/source/fs_fetch_executor.rs:494-505 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
TooManyMethods: Parser src/sqlparser/src/parser.rs:196— TooManyMethods — 248 methods, declared across 2 files: src/parser.rs (245), ast/statement.rs (3). The bar is 30 methods; this is 218 over it, 8.27× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: CatalogController src/meta/src/controller/catalog/mod.rs:119— TooManyMethods — 220 methods, declared across 10 files: controller/fragment.rs (59), catalog/get_op.rs (38), controller/streaming_job.rs (31), catalog/list_op.rs (28), +6 more file(s). The bar is 30 methods; this is 190 over it, 7.33× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: Binder src/frontend/src/binder/mod.rs:94— TooManyMethods — 187 methods, declared across 32 files: expr/mod.rs (34), binder/mod.rs (28), relation/mod.rs (19), function/mod.rs (15), +28 more file(s). The bar is 30 methods; this is 157 over it, 6.23× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: MetaClient src/rpc_client/src/meta_client.rs:141— TooManyMethods — 152 methods. The bar is 30 methods; this is 122 over it, 5.07× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: HummockManager src/meta/src/hummock/manager/mod.rs:154— TooManyMethods — 131 methods, declared across 16 files: compaction/mod.rs (29), manager/versioning.rs (14), manager/mod.rs (12), compaction/compaction_group_manager.rs (11), +12 more file(s). The bar is 30 methods; this is 101 over it, 4.37× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: SchemaCatalog src/frontend/src/catalog/schema_catalog.rs:46— TooManyMethods — 99 methods. The bar is 30 methods; this is 69 over it, 3.30× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: Catalog src/frontend/src/catalog/root_catalog.rs:122— TooManyMethods — 86 methods. The bar is 30 methods; this is 56 over it, 2.87× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: SessionImpl src/frontend/src/session.rs:747— TooManyMethods — 63 methods, declared across 3 files: src/session.rs (48), session/transaction.rs (11), handler/privilege.rs (4). The bar is 30 methods; this is 33 over it, 2.10× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: MetadataManager src/meta/src/manager/metadata.rs:44— TooManyMethods — 56 methods. The bar is 30 methods; this is 26 over it, 1.87× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: ExprImpl src/frontend/src/expr/mod.rs:144— TooManyMethods — 55 methods. The bar is 30 methods; this is 25 over it, 1.83× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: DdlController src/meta/src/rpc/ddl_controller.rs:283— TooManyMethods — 51 methods. The bar is 30 methods; this is 21 over it, 1.70× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: TableCatalog src/frontend/src/catalog/table_catalog.rs:83— TooManyMethods — 49 methods. The bar is 30 methods; this is 19 over it, 1.63× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: Planner src/frontend/src/planner/mod.rs:37— TooManyMethods — 46 methods, declared across 12 files: planner/relation.rs (21), planner/select.rs (8), planner/mod.rs (7), planner/set_operation.rs (2), +8 more file(s). The bar is 30 methods; this is 16 over it, 1.53× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: StateTableInner src/stream/src/common/table/state_table.rs:188— TooManyMethods — 46 methods. The bar is 30 methods; this is 16 over it, 1.53× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: PostgresConnection java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java:85— TooManyMethods — 45 methods. The bar is 30 methods; this is 15 over it, 1.50× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: InflightDatabaseInfo src/meta/src/barrier/info.rs:459— TooManyMethods — 45 methods. The bar is 30 methods; this is 15 over it, 1.50× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: Binding java/java-binding/src/main/java/com/risingwave/java/binding/Binding.java:21— TooManyMethods — 44 methods. The bar is 30 methods; this is 14 over it, 1.47× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: DataChunk src/common/src/array/data_chunk.rs:65— TooManyMethods — 44 methods, declared across 3 files: array/data_chunk.rs (40), array/data_chunk_iter.rs (3), hash/key_v2.rs (1). The bar is 30 methods; this is 14 over it, 1.47× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: PostgresConnectorConfig java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresConnectorConfig.java:62— TooManyMethods — 43 methods. The bar is 30 methods; this is 13 over it, 1.43× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: LogicalJoin src/frontend/src/optimizer/plan_node/logical_join.rs:58— TooManyMethods — 43 methods. The bar is 30 methods; this is 13 over it, 1.43× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: OptimizerContext src/frontend/src/optimizer/optimizer_context.rs:83— TooManyMethods — 41 methods. The bar is 30 methods; this is 11 over it, 1.37× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: Interval src/common/src/types/interval.rs:44— TooManyMethods — 38 methods. The bar is 30 methods; this is 8 over it, 1.27× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: ColIndexMapping src/common/src/util/column_index_mapping.rs:27— TooManyMethods — 36 methods, declared across 2 files: util/column_index_mapping.rs (27), utils/column_index_mapping.rs (9). The bar is 30 methods; this is 6 over it, 1.20× the bar. That list is where to read them, not a suggestion to split the file: the members belong to the type wherever they are declared, so moving them between files leaves the count unchanged. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: Panels grafana/dashboard/common.py:116— TooManyMethods — 34 methods. The bar is 30 methods; this is 4 over it, 1.13× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyMethods: BinlogOffsetContext java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/binlog/BinlogOffsetContext.java:51— TooManyMethods — 33 methods. The bar is 30 methods; this is 3 over it, 1.10× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
risingwave_frontend::handler::handle (cyclomatic 181) src/frontend/src/handler/mod.rs:306— risingwave_frontend::handler::handle has cyclomatic complexity 181 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::expr::type_inference::func::infer_type_for_special (cyclomatic 88) src/frontend/src/expr/type_inference/func.rs:323— risingwave_frontend::expr::type_inference::func::infer_type_for_special has cyclomatic complexity 88 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::handler::create_sink::gen_sink_plan (cyclomatic 53) src/frontend/src/handler/create_sink.rs:151— risingwave_frontend::handler::create_sink::gen_sink_plan has cyclomatic complexity 53 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::handle_privilege::make_prost_privilege (cyclomatic 51) src/frontend/src/handler/handle_privilege.rs:46— risingwave_frontend::handler::handle_privilege::make_prost_privilege has cyclomatic complexity 51 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_frontend::handler::create_index::gen_create_index_plan (cyclomatic 39) src/frontend/src/handler/create_index.rs:143— risingwave_frontend::handler::create_index::gen_create_index_plan has cyclomatic complexity 39 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
risingwave_frontend::binder::expr::bind_data_type (cyclomatic 37) src/frontend/src/binder/expr/mod.rs:1066— risingwave_frontend::binder::expr::bind_data_type has cyclomatic complexity 37 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::stream_fragmenter::build_fragment (cyclomatic 33) src/frontend/src/stream_fragmenter/mod.rs:421— risingwave_frontend::stream_fragmenter::build_fragment has cyclomatic complexity 33 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::handler::explain::do_handle_explain (cyclomatic 33) src/frontend/src/handler/explain.rs:49— risingwave_frontend::handler::explain::do_handle_explain has cyclomatic complexity 33 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::handler::show::handle_show_object (cyclomatic 31) src/frontend/src/handler/show.rs:501— risingwave_frontend::handler::show::handle_show_object has cyclomatic complexity 31 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::optimizer::plan_node::logical_kafka_scan::expr_to_kafka_timestamp_range (cyclomatic 31) src/frontend/src/optimizer/plan_node/logical_kafka_scan.rs:129— risingwave_frontend::optimizer::plan_node::logical_kafka_scan::expr_to_kafka_timestamp_range has cyclomatic complexity 31 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::alter_user::alter_prost_user_info (cyclomatic 29) src/frontend/src/handler/alter_user.rs:34— risingwave_frontend::handler::alter_user::alter_prost_user_info has cyclomatic complexity 29 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
risingwave_frontend::handler::create_source::bind_create_source_or_table_with_connector (cyclomatic 28) src/frontend/src/handler/create_source.rs:885— risingwave_frontend::handler::create_source::bind_create_source_or_table_with_connector has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::create_user::handle_create_user (cyclomatic 26) src/frontend/src/handler/create_user.rs:30— risingwave_frontend::handler::create_user::handle_create_user has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::alter_owner::handle_alter_owner (cyclomatic 25) src/frontend/src/handler/alter_owner.rs:49— risingwave_frontend::handler::alter_owner::handle_alter_owner has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::create_source::validate::validate_compatibility (cyclomatic 25) src/frontend/src/handler/create_source/validate.rs:162— risingwave_frontend::handler::create_source::validate::validate_compatibility has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::create_source::bind_source_pk (cyclomatic 25) src/frontend/src/handler/create_source.rs:519— risingwave_frontend::handler::create_source::bind_source_pk has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::create_source::bind_all_columns (cyclomatic 24) src/frontend/src/handler/create_source.rs:231— risingwave_frontend::handler::create_source::bind_all_columns has cyclomatic complexity 24 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::webhook::websocket::try_handle_connection (cyclomatic 23) src/frontend/src/webhook/websocket.rs:230— risingwave_frontend::webhook::websocket::try_handle_connection has cyclomatic complexity 23 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::handler::create_source::external_schema::bind_columns_from_source_for_non_cdc (cyclomatic 23) src/frontend/src/handler/create_source/external_schema.rs:92— risingwave_frontend::handler::create_source::external_schema::bind_columns_from_source_for_non_cdc has cyclomatic complexity 23 (threshold 15). Of this number, 21 points are the body's own statements and 2 belong to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::optimizer::plan_node::stream_hash_join::derive_watermark_for_hash_join (cyclomatic 22) src/frontend/src/optimizer/plan_node/stream_hash_join.rs:88— risingwave_frontend::optimizer::plan_node::stream_hash_join::derive_watermark_for_hash_join has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::alter_table_column::handle_alter_table_column (cyclomatic 22) src/frontend/src/handler/alter_table_column.rs:118— risingwave_frontend::handler::alter_table_column::handle_alter_table_column has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::create_function::handle_create_function (cyclomatic 19) src/frontend/src/handler/create_function.rs:42— risingwave_frontend::handler::create_function::handle_create_function has cyclomatic complexity 19 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_frontend::optimizer::rule::over_window_to_topn_rule::handle_rank_preds (cyclomatic 18) src/frontend/src/optimizer/rule/over_window_to_topn_rule.rs:299— risingwave_frontend::optimizer::rule::over_window_to_topn_rule::handle_rank_preds has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::handler::alter_set_schema::handle_alter_set_schema (cyclomatic 18) src/frontend/src/handler/alter_set_schema.rs:30— risingwave_frontend::handler::alter_set_schema::handle_alter_set_schema has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_frontend::utils::iceberg_predicate::rw_expr_to_iceberg_predicate (cyclomatic 18) src/frontend/src/utils/iceberg_predicate.rs:178— risingwave_frontend::utils::iceberg_predicate::rw_expr_to_iceberg_predicate has cyclomatic complexity 18 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Parser::parse_table_and_joins (cognitive 59) src/sqlparser/src/parser.rs:5495— Parser::parse_table_and_joins has cognitive complexity 59 (threshold 15). Drivers by points: if/else 16 (40 pts), match/switch 5 (18 pts), loops 1 (nesting depth added 37). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_alter_table (cognitive 51) src/sqlparser/src/parser.rs:3342— Parser::parse_alter_table has cognitive complexity 51 (threshold 15). Drivers by points: if/else 36 (48 pts), boolean chains 3 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_alter_view (cognitive 45) src/sqlparser/src/parser.rs:3628— Parser::parse_alter_view has cognitive complexity 45 (threshold 15). Drivers by points: if/else 24 (35 pts), boolean chains 10 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_infix (cognitive 42) src/sqlparser/src/parser.rs:1300— Parser::parse_infix has cognitive complexity 42 (threshold 15). Drivers by points: if/else 25 (34 pts), match/switch 4 (8 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_prefix (cognitive 39) src/sqlparser/src/parser.rs:584— Parser::parse_prefix has cognitive complexity 39 (threshold 15). Drivers by points: if/else 15 (28 pts), match/switch 4 (9 pts), boolean chains 2 (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_alter_sink (cognitive 35) src/sqlparser/src/parser.rs:3747— Parser::parse_alter_sink has cognitive complexity 35 (threshold 15). Drivers by points: if/else 23 (32 pts), boolean chains 3 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_alter_source (cognitive 33) src/sqlparser/src/parser.rs:3901— Parser::parse_alter_source has cognitive complexity 33 (threshold 15). Drivers by points: if/else 23 (31 pts), boolean chains 2 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_format_encode_with_connector (cognitive 29) src/sqlparser/src/ast/statement.rs:237— Parser::parse_format_encode_with_connector has cognitive complexity 29 (threshold 15). Drivers by points: if/else 17 (28 pts), boolean chains 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_create_table (cognitive 29) src/sqlparser/src/parser.rs:2594— Parser::parse_create_table has cognitive complexity 29 (threshold 15). Drivers by points: if/else 21 (27 pts), boolean chains 2 (nesting depth added 6). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
Parser::parse_alter_index (cognitive 29) src/sqlparser/src/parser.rs:3543— Parser::parse_alter_index has cognitive complexity 29 (threshold 15). Drivers by points: if/else 17 (26 pts), boolean chains 3 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_alter_database (cognitive 24) src/sqlparser/src/parser.rs:3257— Parser::parse_alter_database has cognitive complexity 24 (threshold 15). Drivers by points: if/else 14 (23 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_optional_pattern_quantifier (cognitive 24) src/sqlparser/src/parser.rs:6023— Parser::parse_optional_pattern_quantifier has cognitive complexity 24 (threshold 15). Drivers by points: if/else 11 (16 pts), match/switch 3 (7 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_create_database (cognitive 23) src/sqlparser/src/parser.rs:2046— Parser::parse_create_database has cognitive complexity 23 (threshold 15). Drivers by points: if/else 8 (19 pts), match/switch 1 (3 pts), loops 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_optional_column_option (cognitive 21) src/sqlparser/src/parser.rs:2871— Parser::parse_optional_column_option has cognitive complexity 21 (threshold 15). Drivers by points: if/else 14 (17 pts), boolean chains 2, loops 1 (2 pts) (nesting depth added 4). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
Parser::parse_table_factor_inner (cognitive 21) src/sqlparser/src/parser.rs:5658— Parser::parse_table_factor_inner has cognitive complexity 21 (threshold 15). Drivers by points: if/else 13 (19 pts), match/switch 1 (2 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_create (cognitive 20) src/sqlparser/src/parser.rs:1976— Parser::parse_create has cognitive complexity 20 (threshold 15). Drivers by points: if/else 19 (20 pts) (nesting depth added 1). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
Parser::parse_columns_with_watermark (cognitive 19) src/sqlparser/src/parser.rs:2794— Parser::parse_columns_with_watermark has cognitive complexity 19 (threshold 15). Drivers by points: if/else 11 (17 pts), boolean chains 1, loops 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_optional_table_constraint (cognitive 18) src/sqlparser/src/parser.rs:2983— Parser::parse_optional_table_constraint has cognitive complexity 18 (threshold 15). Drivers by points: if/else 8 (12 pts), boolean chains 3, loops 1 (2 pts), match/switch 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_alter (cognitive 18) src/sqlparser/src/parser.rs:3215— Parser::parse_alter has cognitive complexity 18 (threshold 15). Drivers by points: if/else 18. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
Parser::parse_query (cognitive 18) src/sqlparser/src/parser.rs:4914— Parser::parse_query has cognitive complexity 18 (threshold 15). Drivers by points: if/else 10 (14 pts), boolean chains 3, loops 1 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_grant_revoke_privileges_objects (cognitive 18) src/sqlparser/src/parser.rs:6182— Parser::parse_grant_revoke_privileges_objects has cognitive complexity 18 (threshold 15). Drivers by points: if/else 14 (15 pts), match/switch 1 (3 pts) (nesting depth added 3). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
Parser::parse_set (cognitive 17) src/sqlparser/src/parser.rs:5173— Parser::parse_set has cognitive complexity 17 (threshold 15). Drivers by points: if/else 6 (10 pts), match/switch 2 (5 pts), boolean chains 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Parser::parse_alter_subscription (cognitive 16) src/sqlparser/src/parser.rs:3855— Parser::parse_alter_subscription has cognitive complexity 16 (threshold 15). Drivers by points: if/else 11 (15 pts), boolean chains 1 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_builtin_scalar_function (cognitive 77) src/frontend/src/binder/expr/function/builtin_scalar.rs:31— Binder::bind_builtin_scalar_function has cognitive complexity 77 (threshold 15). Drivers by points: if/else 53 (59 pts), boolean chains 9, match/switch 5 (6 pts), loops 3 (nesting depth added 7). Of this number, 73 points are the body's own statements and 4 belong to 2 function items inside it that branch. To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
Binder::bind_gap_fill (cognitive 65) src/frontend/src/binder/relation/gap_fill.rs:36— Binder::bind_gap_fill has cognitive complexity 65 (threshold 15). Drivers by points: if/else 19 (54 pts), loops 3 (6 pts), match/switch 1 (3 pts), boolean chains 2 (nesting depth added 40). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
Binder::bind_function (cognitive 61) src/frontend/src/binder/expr/function/mod.rs:173— Binder::bind_function has cognitive complexity 61 (threshold 15). Drivers by points: if/else 39 (52 pts), boolean chains 6, match/switch 2 (3 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_match_recognize (cognitive 50) src/frontend/src/binder/relation/match_recognize.rs:148— Binder::bind_match_recognize has cognitive complexity 50 (threshold 15). Drivers by points: if/else 16 (31 pts), loops 9 (10 pts), match/switch 4 (7 pts), boolean chains 2 (nesting depth added 19). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_catalog_relation_by_name (cognitive 44) src/frontend/src/binder/relation/table_or_source.rs:110— Binder::bind_catalog_relation_by_name has cognitive complexity 44 (threshold 15). Drivers by points: if/else 21 (36 pts), boolean chains 5, loops 1 (2 pts), match/switch 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::lower_measure (cognitive 42) src/frontend/src/binder/relation/match_recognize.rs:540— Binder::lower_measure has cognitive complexity 42 (threshold 15). Drivers by points: if/else 21 (34 pts), boolean chains 6, match/switch 1 (2 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_insert (cognitive 36) src/frontend/src/binder/insert.rs:104— Binder::bind_insert has cognitive complexity 36 (threshold 15). Drivers by points: if/else 23 (32 pts), boolean chains 2, match/switch 2 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_join_constraint (cognitive 33) src/frontend/src/binder/relation/join.rs:141— Binder::bind_join_constraint has cognitive complexity 33 (threshold 15). Drivers by points: if/else 5 (16 pts), match/switch 4 (9 pts), loops 3 (7 pts), boolean chains 1 (nesting depth added 20). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Binder::bind_window_function (cognitive 29) src/frontend/src/binder/expr/function/window.rs:58— Binder::bind_window_function has cognitive complexity 29 (threshold 15). Drivers by points: if/else 11 (18 pts), match/switch 5 (11 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_update (cognitive 29) src/frontend/src/binder/update.rs:125— Binder::bind_update has cognitive complexity 29 (threshold 15). Drivers by points: if/else 9 (15 pts), loops 5 (11 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_grouping_items_expr_in_select (cognitive 22) src/frontend/src/binder/select.rs:488— Binder::bind_grouping_items_expr_in_select has cognitive complexity 22 (threshold 15). Drivers by points: match/switch 5 (19 pts), loops 2 (3 pts) (nesting depth added 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Binder::bind_column (cognitive 21) src/frontend/src/binder/expr/column.rs:23— Binder::bind_column has cognitive complexity 21 (threshold 15). Drivers by points: if/else 7 (11 pts), match/switch 4 (6 pts), boolean chains 3, loops 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_table_function (cognitive 20) src/frontend/src/binder/relation/table_function.rs:36— Binder::bind_table_function has cognitive complexity 20 (threshold 15). Drivers by points: if/else 14 (19 pts), boolean chains 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::corresponding (cognitive 20) src/frontend/src/binder/set_expr.rs:234— Binder::corresponding has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (13 pts), loops 3 (5 pts), boolean chains 2 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::resolve_iceberg_metadata_relation (cognitive 19) src/frontend/src/binder/relation/table_or_source.rs:303— Binder::resolve_iceberg_metadata_relation has cognitive complexity 19 (threshold 15). Drivers by points: if/else 12 (17 pts), boolean chains 1, match/switch 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::check_privilege (cognitive 19) src/frontend/src/binder/relation/table_or_source.rs:472— Binder::check_privilege has cognitive complexity 19 (threshold 15). Drivers by points: if/else 7 (15 pts), boolean chains 3, match/switch 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::check_convert_simple_form (cognitive 18) src/frontend/src/binder/expr/mod.rs:764— Binder::check_convert_simple_form has cognitive complexity 18 (threshold 15). Drivers by points: if/else 9 (17 pts), loops 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_expr_inner (cognitive 17) src/frontend/src/binder/expr/mod.rs:66— Binder::bind_expr_inner has cognitive complexity 17 (threshold 15). Drivers by points: if/else 10 (15 pts), boolean chains 1, match/switch 1 (nesting depth added 5). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Binder::check_constant_case_when_optimization (cognitive 17) src/frontend/src/binder/expr/mod.rs:645— Binder::check_constant_case_when_optimization has cognitive complexity 17 (threshold 15). Drivers by points: if/else 9 (16 pts), loops 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::correlation_contexts (cognitive 16) src/frontend/src/binder/expr/column.rs:151— Binder::correlation_contexts has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 3 (4 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Binder::bind_ordered_set_agg (cognitive 16) src/frontend/src/binder/expr/function/aggregate.rs:98— Binder::bind_ordered_set_agg has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (11 pts), match/switch 2 (3 pts), boolean chains 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (15 lines × 2) src/batch/executors/src/executor/join/mod.rs:111— src/batch/executors/src/executor/join/mod.rs:111-125 | src/stream/src/executor/join/mod.rs:86-100 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (15 lines × 2) src/expr/impl/src/udf/wasm.rs:63— src/expr/impl/src/udf/wasm.rs:63-77 | src/expr/impl/src/udf/wasm.rs:151-165 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/expr/macro/src/parse.rs:293— src/expr/macro/src/parse.rs:293-307 | src/frontend/macro/src/lib.rs:77-91 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (15 lines × 2) src/frontend/src/metrics_reader.rs:213— src/frontend/src/metrics_reader.rs:213-227 | src/frontend/src/metrics_reader.rs:233-247 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/frontend/src/optimizer/plan_node/batch_hop_window.rs:172— src/frontend/src/optimizer/plan_node/batch_hop_window.rs:172-186 | src/frontend/src/optimizer/plan_node/stream_hop_window.rs:141-155 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (15 lines × 2) src/frontend/src/optimizer/plan_node/logical_agg.rs:1541— src/frontend/src/optimizer/plan_node/logical_agg.rs:1541-1555 | src/frontend/src/optimizer/plan_node/logical_topn.rs:338-352 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (15 lines × 2) src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:148— src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:148-162 | src/frontend/src/optimizer/rule/top_n_on_index_rule.rs:85-99 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (15 lines × 2) src/frontend/src/scheduler/distributed/stage.rs:748— src/frontend/src/scheduler/distributed/stage.rs:748-762 | src/frontend/src/scheduler/local.rs:655-669 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (15 lines × 2) src/frontend/src/handler/alter_set_schema.rs:97— src/frontend/src/handler/alter_set_schema.rs:97-111 | src/frontend/src/handler/alter_set_schema.rs:114-128 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/meta/src/hummock/compaction/selector/tombstone_compaction_selector.rs:60— src/meta/src/hummock/compaction/selector/tombstone_compaction_selector.rs:60-74 | src/meta/src/hummock/compaction/selector/ttl_selector.rs:55-69 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (15 lines × 2) src/meta/src/stream/stream_manager.rs:1073— src/meta/src/stream/stream_manager.rs:1073-1087 | src/meta/src/stream/stream_manager.rs:1104-1118 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/meta/src/controller/catalog/util.rs:442— src/meta/src/controller/catalog/util.rs:442-456 | src/meta/src/controller/catalog/util.rs:490-504 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/object_store/src/object/s3.rs:287— src/object_store/src/object/s3.rs:287-301 | src/object_store/src/object/s3.rs:367-381 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/storage/src/hummock/iterator/skip_watermark.rs:524— src/storage/src/hummock/iterator/skip_watermark.rs:524-538 | src/storage/src/hummock/iterator/skip_watermark.rs:595-609 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/storage/src/hummock/store/local_hummock_storage.rs:905— src/storage/src/hummock/store/local_hummock_storage.rs:905-919 | src/storage/src/hummock/store/local_hummock_storage.rs:1024-1038 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/stream/src/executor/backfill/arrangement_backfill.rs:341— src/stream/src/executor/backfill/arrangement_backfill.rs:341-355 | src/stream/src/executor/backfill/arrangement_backfill.rs:394-408 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/stream/src/executor/eowc/eowc_gap_fill.rs:105— src/stream/src/executor/eowc/eowc_gap_fill.rs:105-119 | src/stream/src/executor/eowc/eowc_gap_fill.rs:125-139 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/stream/src/executor/source/fs_fetch_executor.rs:295— src/stream/src/executor/source/fs_fetch_executor.rs:295-309 | src/stream/src/executor/source/iceberg_fetch_executor.rs:279-293 — before extracting anything, compare `src/stream/src/executor/source/fs_fetch_executor.rs` and `src/stream/src/executor/source/iceberg_fetch_executor.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 71 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (15 lines × 2) src/connector/src/sink/iceberg/writer.rs:1047— src/connector/src/sink/iceberg/writer.rs:1047-1061 | src/connector/src/sink/iceberg/writer.rs:1066-1082 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) src/storage/src/hummock/compactor/shared_buffer_compact.rs:83— src/storage/src/hummock/compactor/shared_buffer_compact.rs:83-97 | src/storage/src/hummock/compactor/shared_buffer_compact.rs:98-112 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 2) integration_tests/scripts/compatibility/cli.py:37— integration_tests/scripts/compatibility/cli.py:37-51 | integration_tests/scripts/compatibility/cli.py:60-74 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
risingwave_meta::controller::system_param::merge_params (cognitive 54) src/meta/src/controller/system_param.rs:112— risingwave_meta::controller::system_param::merge_params has cognitive complexity 54 (threshold 15). Drivers by points: if/else 18 (36 pts), match/switch 18 (nesting depth added 18). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_meta::dashboard::handlers::get_streaming_stats_from_prometheus (cognitive 54) src/meta/src/dashboard/mod.rs:778— risingwave_meta::dashboard::handlers::get_streaming_stats_from_prometheus has cognitive complexity 54 (threshold 15). Drivers by points: if/else 14 (33 pts), loops 8 (17 pts), boolean chains 4 (nesting depth added 28). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::controller::utils::check_relation_name_duplicate (cognitive 45) src/meta/src/controller/utils.rs:803— risingwave_meta::controller::utils::check_relation_name_duplicate has cognitive complexity 45 (threshold 15). Drivers by points: if/else 30 (40 pts), boolean chains 5 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::serving::start_serving_vnode_mapping_worker (cognitive 42) src/meta/src/serving/mod.rs:267— risingwave_meta::serving::start_serving_vnode_mapping_worker has cognitive complexity 42 (threshold 15). Drivers by points: if/else 6 (26 pts), match/switch 4 (14 pts), boolean chains 1, loops 1 (nesting depth added 30). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::stream::stream_graph::state_match::match_graph::dfs (cognitive 26) src/meta/src/stream/stream_graph/state_match.rs:442— risingwave_meta::stream::stream_graph::state_match::match_graph::dfs has cognitive complexity 26 (threshold 15). Drivers by points: if/else 6 (11 pts), loops 4 (8 pts), match/switch 2 (5 pts), boolean chains 2 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::hummock::metrics_utils::trigger_sst_stat (cognitive 25) src/meta/src/hummock/metrics_utils.rs:138— risingwave_meta::hummock::metrics_utils::trigger_sst_stat has cognitive complexity 25 (threshold 15). Drivers by points: if/else 7 (14 pts), loops 4 (7 pts), boolean chains 4 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::manager::iceberg_compaction::gc::plan_manifest_rewrite (cognitive 23) src/meta/src/manager/iceberg_compaction/gc.rs:39— risingwave_meta::manager::iceberg_compaction::gc::plan_manifest_rewrite has cognitive complexity 23 (threshold 15). Drivers by points: if/else 7 (15 pts), boolean chains 4, loops 3 (4 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::controller::scale::find_no_shuffle_graphs (cognitive 22) src/meta/src/controller/scale.rs:1636— risingwave_meta::controller::scale::find_no_shuffle_graphs has cognitive complexity 22 (threshold 15). Drivers by points: if/else 4 (11 pts), loops 4 (8 pts), match/switch 1 (3 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::hummock::manager::table_change_log::resolve_table_change_log_truncate_epochs (cognitive 21) src/meta/src/hummock/manager/table_change_log.rs:43— risingwave_meta::hummock::manager::table_change_log::resolve_table_change_log_truncate_epochs has cognitive complexity 21 (threshold 15). Drivers by points: if/else 4 (10 pts), loops 5 (8 pts), match/switch 1 (3 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::dashboard::handlers::get_streaming_stats (cognitive 20) src/meta/src/dashboard/mod.rs:699— risingwave_meta::dashboard::handlers::get_streaming_stats has cognitive complexity 20 (threshold 15). Drivers by points: if/else 6 (12 pts), loops 5 (8 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::manager::iceberg_pk_index_sink::coordinator::coalesce_position_delete_files (cognitive 19) src/meta/src/manager/iceberg_pk_index_sink/coordinator.rs:813— risingwave_meta::manager::iceberg_pk_index_sink::coordinator::coalesce_position_delete_files has cognitive complexity 19 (threshold 15). Drivers by points: if/else 8 (12 pts), loops 5 (6 pts), boolean chains 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::stream::source_manager::split_assignment::reassign_splits (cognitive 19) src/meta/src/stream/source_manager/split_assignment.rs:508— risingwave_meta::stream::source_manager::split_assignment::reassign_splits has cognitive complexity 19 (threshold 15). Drivers by points: if/else 9 (13 pts), boolean chains 4, loops 2 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::hummock::manager::compaction::compaction_group_manager::update_compaction_config (cognitive 18) src/meta/src/hummock/manager/compaction/compaction_group_manager.rs:660— risingwave_meta::hummock::manager::compaction::compaction_group_manager::update_compaction_config has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (15 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::barrier::checkpoint::state::render_actors (cognitive 18) src/meta/src/barrier/checkpoint/state.rs:266— risingwave_meta::barrier::checkpoint::state::render_actors has cognitive complexity 18 (threshold 15). Drivers by points: loops 6 (12 pts), if/else 3 (6 pts) (nesting depth added 9). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_meta::stream::stream_graph::assignment::assign_hierarchical (cognitive 18) src/meta/src/stream/stream_graph/assignment.rs:382— risingwave_meta::stream::stream_graph::assignment::assign_hierarchical has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (9 pts), loops 4 (7 pts), match/switch 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::stream::scale::build_reschedule_commands (cognitive 18) src/meta/src/stream/scale.rs:820— risingwave_meta::stream::scale::build_reschedule_commands has cognitive complexity 18 (threshold 15). Drivers by points: loops 5 (11 pts), match/switch 1 (4 pts), if/else 2 (3 pts) (nesting depth added 10). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_meta::barrier::checkpoint::state::resolve_no_shuffle_ensembles (cognitive 17) src/meta/src/barrier/checkpoint/state.rs:187— risingwave_meta::barrier::checkpoint::state::resolve_no_shuffle_ensembles has cognitive complexity 17 (threshold 15). Drivers by points: if/else 5 (10 pts), loops 5 (7 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::stream::stream_graph::fragment::rewrite_refresh_schema_sink_fragment (cognitive 16) src/meta/src/stream/stream_graph/fragment.rs:749— risingwave_meta::stream::stream_graph::fragment::rewrite_refresh_schema_sink_fragment has cognitive complexity 16 (threshold 15). Drivers by points: if/else 13 (15 pts), boolean chains 1 (nesting depth added 2). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
risingwave_meta::manager::iceberg_pk_index_sink::coordinator::probe_committed_data_files (cognitive 16) src/meta/src/manager/iceberg_pk_index_sink/coordinator.rs:556— risingwave_meta::manager::iceberg_pk_index_sink::coordinator::probe_committed_data_files has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (13 pts), loops 2 (3 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_meta::stream::stream_graph::assignment::assign_items_weighted_with_scale_fn (cognitive 16) src/meta/src/stream/stream_graph/assignment.rs:96— risingwave_meta::stream::stream_graph::assignment::assign_items_weighted_with_scale_fn has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (7 pts), loops 3 (4 pts), match/switch 2 (4 pts), boolean chains 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (16 lines × 2) src/batch/executors/src/executor/sort_over_window.rs:63— src/batch/executors/src/executor/sort_over_window.rs:63-78 | src/stream/src/from_proto/over_window.rs:42-57 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (16 lines × 2) src/frontend/src/optimizer/plan_node/batch_kafka_scan.rs:123— src/frontend/src/optimizer/plan_node/batch_kafka_scan.rs:123-138 | src/frontend/src/optimizer/plan_node/batch_source.rs:107-122 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (16 lines × 2) src/frontend/src/optimizer/plan_node/logical_dedup.rs:93— src/frontend/src/optimizer/plan_node/logical_dedup.rs:93-108 | src/frontend/src/optimizer/plan_node/logical_over_window.rs:729-744 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (16 lines × 2) src/frontend/src/optimizer/rule/batch/batch_project_merge_rule.rs:29— src/frontend/src/optimizer/rule/batch/batch_project_merge_rule.rs:29-44 | src/frontend/src/optimizer/rule/stream/stream_project_merge_rule.rs:29-44 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (16 lines × 2) src/meta/src/barrier/checkpoint/recovery.rs:394— src/meta/src/barrier/checkpoint/recovery.rs:394-409 | src/meta/src/barrier/checkpoint/recovery.rs:476-491 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/meta/src/controller/streaming_job.rs:593— src/meta/src/controller/streaming_job.rs:593-608 | src/meta/src/controller/streaming_job.rs:666-681 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/meta/src/controller/catalog/alter_op.rs:137— src/meta/src/controller/catalog/alter_op.rs:137-152 | src/meta/src/controller/catalog/alter_op.rs:230-245 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/storage/src/hummock/store/version.rs:906— src/storage/src/hummock/store/version.rs:906-921 | src/storage/src/hummock/store/version.rs:955-970 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/stream/src/executor/asof_join.rs:425— src/stream/src/executor/asof_join.rs:425-440 | src/stream/src/executor/asof_join.rs:451-466 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/stream/src/executor/asof_join.rs:435— src/stream/src/executor/asof_join.rs:435-450 | src/stream/src/executor/hash_join.rs:701-716 — before extracting anything, compare `src/stream/src/executor/asof_join.rs` and `src/stream/src/executor/hash_join.rs` as WHOLE FILES: this scan already matched 13 separate duplicated blocks between them, totalling at least 244 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (16 lines × 2) src/stream/src/executor/asof_join.rs:622— src/stream/src/executor/asof_join.rs:622-637 | src/stream/src/executor/asof_join.rs:724-739 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/stream/src/executor/eowc/eowc_gap_fill.rs:191— src/stream/src/executor/eowc/eowc_gap_fill.rs:191-206 | src/stream/src/executor/gap_fill.rs:381-396 — before extracting anything, compare `src/stream/src/executor/eowc/eowc_gap_fill.rs` and `src/stream/src/executor/gap_fill.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 78 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (16 lines × 2) src/stream/src/executor/gap_fill.rs:632— src/stream/src/executor/gap_fill.rs:632-647 | src/stream/src/executor/gap_fill.rs:752-767 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/stream/src/executor/hash_join.rs:691— src/stream/src/executor/hash_join.rs:691-706 | src/stream/src/executor/hash_join.rs:719-734 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) src/stream/src/executor/top_n/top_n_appendonly.rs:87— src/stream/src/executor/top_n/top_n_appendonly.rs:87-102 | src/stream/src/executor/top_n/top_n_plain.rs:113-128 — before extracting anything, compare `src/stream/src/executor/top_n/top_n_appendonly.rs` and `src/stream/src/executor/top_n/top_n_plain.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 32 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (16 lines × 2) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java:354— java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java:354-369 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/JDBCSink.java:396-411 — before extracting anything, compare `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java` and `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/JDBCSink.java` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 97 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Each matched range is the entire body of the declaration above it, so the region is already a complete unit: move that whole declaration to the shared location and have each site call it, rather than lifting the lines out of their bodies. Any `return` inside it is the body's own exit and keeps its meaning in the moved unit.
Duplicated block (16 lines × 2) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:313— java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:313-328 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java:280-295 — before extracting anything, compare `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java` and `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 34 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:313` it runs out through the closing brace of the declaration holding it — the window is that declaration's tail, not a fragment that begins part-way through something, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (16 lines × 2) src/stream/src/executor/test_utils/hash_join_executor.rs:169— src/stream/src/executor/test_utils/hash_join_executor.rs:169-184 | src/stream/src/executor/test_utils/hash_join_executor.rs:200-215 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16 lines × 2) REDACTED:449— REDACTED:449-464 | REDACTED:483-498 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
risingwave_connector::sink::sqlserver::bind_params (cyclomatic 52) src/connector/src/sink/sqlserver.rs:770— risingwave_connector::sink::sqlserver::bind_params has cyclomatic complexity 52 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::sink::encoder::avro::on_field (cyclomatic 52) src/connector/src/sink/encoder/avro.rs:411— risingwave_connector::sink::encoder::avro::on_field has cyclomatic complexity 52 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::sink::encoder::proto::on_field (cyclomatic 49) src/connector/src/sink/encoder/proto.rs:314— risingwave_connector::sink::encoder::proto::on_field has cyclomatic complexity 49 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::sink::encoder::json::datum_to_json_object (cyclomatic 40) src/connector/src/sink/encoder/json.rs:230— risingwave_connector::sink::encoder::json::datum_to_json_object has cyclomatic complexity 40 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::parser::unified::debezium::extract_bson_field (cyclomatic 37) src/connector/src/parser/unified/debezium.rs:809— risingwave_connector::parser::unified::debezium::extract_bson_field has cyclomatic complexity 37 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_connector::source::cdc::external::mysql::mysql_type_to_rw_type (cyclomatic 36) src/connector/src/source/cdc/external/mysql.rs:448— risingwave_connector::source::cdc::external::mysql::mysql_type_to_rw_type has cyclomatic complexity 36 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing. This is NOT this file's highest cyclomatic complexity: risingwave_connector::source::cdc::external::mysql::type_name_to_mysql_type (cyclomatic 49) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
risingwave_connector::parser::unified::debezium::bson_extract_number (cyclomatic 35) src/connector/src/parser/unified/debezium.rs:997— risingwave_connector::parser::unified::debezium::bson_extract_number has cyclomatic complexity 35 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_connector::parser::unified::debezium::parse_schema_change (cyclomatic 28) src/connector/src/parser/unified/debezium.rs:294— risingwave_connector::parser::unified::debezium::parse_schema_change has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_connector::sink::encoder::bson::datum_to_bson (cyclomatic 27) src/connector/src/sink/encoder/bson.rs:103— risingwave_connector::sink::encoder::bson::datum_to_bson has cyclomatic complexity 27 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::parser::mysql::mysql_datum_to_rw_datum (cyclomatic 25) src/connector/src/parser/mysql.rs:109— risingwave_connector::parser::mysql::mysql_datum_to_rw_datum has cyclomatic complexity 25 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::parser::parse_message_stream (cyclomatic 22) src/connector/src/parser/mod.rs:378— risingwave_connector::parser::parse_message_stream has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_connector::sink::iceberg::create_table::create_table_if_not_exists_impl (cyclomatic 21) src/connector/src/sink/iceberg/create_table.rs:126— risingwave_connector::sink::iceberg::create_table::create_table_if_not_exists_impl has cyclomatic complexity 21 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::sink::http::validate_http_sink (cyclomatic 19) src/connector/src/sink/http.rs:97— risingwave_connector::sink::http::validate_http_sink has cyclomatic complexity 19 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::parser::unified::debezium::extract_bson_id (cyclomatic 17) src/connector/src/parser/unified/debezium.rs:742— risingwave_connector::parser::unified::debezium::extract_bson_id has cyclomatic complexity 17 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::sink::deltalake::check_field_type (cyclomatic 17) src/connector/src/sink/deltalake.rs:281— risingwave_connector::sink::deltalake::check_field_type has cyclomatic complexity 17 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector::sink::iceberg::create_table::field_is_compatible (cyclomatic 16) src/connector/src/sink/iceberg/create_table.rs:366— risingwave_connector::sink::iceberg::create_table::field_is_compatible has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Parser::parse_infix (cyclomatic 47) src/sqlparser/src/parser.rs:1300— Parser::parse_infix has cyclomatic complexity 47 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Parser::parse_prefix (cyclomatic 43) src/sqlparser/src/parser.rs:584— Parser::parse_prefix has cyclomatic complexity 43 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Parser::parse_alter_table (cyclomatic 33) src/sqlparser/src/parser.rs:3342— Parser::parse_alter_table has cyclomatic complexity 33 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_alter_view (cyclomatic 31) src/sqlparser/src/parser.rs:3628— Parser::parse_alter_view has cyclomatic complexity 31 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_table_and_joins (cyclomatic 28) src/sqlparser/src/parser.rs:5495— Parser::parse_table_and_joins has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_optional_pattern_quantifier (cyclomatic 26) src/sqlparser/src/parser.rs:6023— Parser::parse_optional_pattern_quantifier has cyclomatic complexity 26 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_show (cyclomatic 25) src/sqlparser/src/parser.rs:5244— Parser::parse_show has cyclomatic complexity 25 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_alter_sink (cyclomatic 23) src/sqlparser/src/parser.rs:3747— Parser::parse_alter_sink has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_grant_revoke_privileges_objects (cyclomatic 23) src/sqlparser/src/parser.rs:6182— Parser::parse_grant_revoke_privileges_objects has cyclomatic complexity 23 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_alter_source (cyclomatic 22) src/sqlparser/src/parser.rs:3901— Parser::parse_alter_source has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_create (cyclomatic 19) src/sqlparser/src/parser.rs:1976— Parser::parse_create has cyclomatic complexity 19 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_alter (cyclomatic 18) src/sqlparser/src/parser.rs:3215— Parser::parse_alter has cyclomatic complexity 18 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_alter_index (cyclomatic 17) src/sqlparser/src/parser.rs:3543— Parser::parse_alter_index has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_format_encode_with_connector (cyclomatic 16) src/sqlparser/src/ast/statement.rs:237— Parser::parse_format_encode_with_connector has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Parser::parse_create_table (cyclomatic 16) src/sqlparser/src/parser.rs:2594— Parser::parse_create_table has cyclomatic complexity 16 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
Parser::parse_value_and_obj_ref (cyclomatic 16) src/sqlparser/src/parser.rs:4252— Parser::parse_value_and_obj_ref has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing. This is NOT this file's highest cyclomatic complexity: Parser::parse_statement (cyclomatic 43) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
risingwave_connector::parser::unified::debezium::parse_schema_change (cognitive 115) src/connector/src/parser/unified/debezium.rs:294— risingwave_connector::parser::unified::debezium::parse_schema_change has cognitive complexity 115 (threshold 15). Drivers by points: match/switch 10 (61 pts), if/else 13 (45 pts), loops 2 (6 pts), boolean chains 3 (nesting depth added 87). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_connector::parser::parse_message_stream (cognitive 69) src/connector/src/parser/mod.rs:378— risingwave_connector::parser::parse_message_stream has cognitive complexity 69 (threshold 15). Drivers by points: if/else 10 (36 pts), loops 6 (19 pts), match/switch 4 (14 pts) (nesting depth added 49). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::encoder::avro::on_field (cognitive 48) src/connector/src/sink/encoder/avro.rs:411— risingwave_connector::sink::encoder::avro::on_field has cognitive complexity 48 (threshold 15). Drivers by points: match/switch 23 (42 pts), if/else 3 (6 pts) (nesting depth added 22). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_connector::parser::unified::debezium::extract_bson_field (cognitive 45) src/connector/src/parser/unified/debezium.rs:809— risingwave_connector::parser::unified::debezium::extract_bson_field has cognitive complexity 45 (threshold 15). Drivers by points: if/else 20 (32 pts), boolean chains 5, loops 2 (4 pts), match/switch 3 (4 pts) (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::encoder::proto::on_field (cognitive 43) src/connector/src/sink/encoder/proto.rs:314— risingwave_connector::sink::encoder::proto::on_field has cognitive complexity 43 (threshold 15). Drivers by points: match/switch 21 (36 pts), if/else 4 (5 pts), boolean chains 2 (nesting depth added 16). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_connector::parser::unified::debezium::bson_extract_number (cognitive 41) src/connector/src/parser/unified/debezium.rs:997— risingwave_connector::parser::unified::debezium::bson_extract_number has cognitive complexity 41 (threshold 15). Drivers by points: if/else 16 (26 pts), match/switch 6 (13 pts), boolean chains 2 (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::iceberg::metadata::scan_iceberg_metadata (cognitive 31) src/connector/src/sink/iceberg/metadata.rs:143— risingwave_connector::sink::iceberg::metadata::scan_iceberg_metadata has cognitive complexity 31 (threshold 15). Drivers by points: if/else 7 (18 pts), loops 4 (12 pts), match/switch 1 (nesting depth added 19). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::encoder::json::datum_to_json_object (cognitive 29) src/connector/src/sink/encoder/json.rs:230— risingwave_connector::sink::encoder::json::datum_to_json_object has cognitive complexity 29 (threshold 15). Drivers by points: match/switch 9 (16 pts), loops 4 (10 pts), if/else 2 (3 pts) (nesting depth added 14). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_connector::sink::iceberg::create_table::create_table_if_not_exists_impl (cognitive 23) src/connector/src/sink/iceberg/create_table.rs:126— risingwave_connector::sink::iceberg::create_table::create_table_if_not_exists_impl has cognitive complexity 23 (threshold 15). Drivers by points: if/else 9 (12 pts), match/switch 5 (7 pts), boolean chains 2, loops 1 (2 pts) (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::iceberg::create_table::parse_order_key_exprs (cognitive 21) src/connector/src/sink/iceberg/create_table.rs:540— risingwave_connector::sink::iceberg::create_table::parse_order_key_exprs has cognitive complexity 21 (threshold 15). Drivers by points: if/else 6 (11 pts), match/switch 2 (7 pts), loops 2 (3 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::source::iceberg::scan_task_to_chunk_with_deletes (cognitive 21) src/connector/src/source/iceberg/mod.rs:465— risingwave_connector::source::iceberg::scan_task_to_chunk_with_deletes has cognitive complexity 21 (threshold 15). Drivers by points: if/else 10 (18 pts), boolean chains 1, loops 1, match/switch 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::http::validate_http_sink (cognitive 21) src/connector/src/sink/http.rs:97— risingwave_connector::sink::http::validate_http_sink has cognitive complexity 21 (threshold 15). Drivers by points: if/else 6 (9 pts), match/switch 4 (7 pts), loops 2 (3 pts), boolean chains 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::iceberg::create_table::field_is_compatible (cognitive 19) src/connector/src/sink/iceberg/create_table.rs:366— risingwave_connector::sink::iceberg::create_table::field_is_compatible has cognitive complexity 19 (threshold 15). Drivers by points: if/else 5 (11 pts), boolean chains 3, match/switch 2 (3 pts), loops 1 (2 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector::sink::sqlserver::bind_params (cognitive 18) src/connector/src/sink/sqlserver.rs:770— risingwave_connector::sink::sqlserver::bind_params has cognitive complexity 18 (threshold 15). Drivers by points: match/switch 6 (17 pts), loops 1 (nesting depth added 11). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_connector::parser::mysql::mysql_datum_to_rw_datum (cognitive 16) src/connector/src/parser/mysql.rs:109— risingwave_connector::parser::mysql::mysql_datum_to_rw_datum has cognitive complexity 16 (threshold 15). Drivers by points: match/switch 6 (14 pts), if/else 1 (2 pts) (nesting depth added 9). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_connector::sink::encoder::bson::datum_to_bson (cognitive 16) src/connector/src/sink/encoder/bson.rs:103— risingwave_connector::sink::encoder::bson::datum_to_bson has cognitive complexity 16 (threshold 15). Drivers by points: if/else 3 (8 pts), match/switch 4 (6 pts), loops 1 (2 pts) (nesting depth added 8). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
TooManyFields: StreamingMetrics src/stream/src/executor/monitor/streaming_stats.rs:45— TooManyFields — 137 stored fields beside 18 methods. The bar is 30 stored fields; this is 107 over it, 4.57× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: StorageOpts src/storage/src/opts.rs:24— TooManyFields — 117 stored fields. The bar is 30 stored fields; this is 87 over it, 3.90× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: MetaOpts src/meta/src/manager/env.rs:95— TooManyFields — 100 stored fields beside 1 method. The bar is 30 stored fields; this is 70 over it, 3.33× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: MetaMetrics src/meta/src/rpc/metrics.rs:73— TooManyFields — 93 stored fields beside 1 method. The bar is 30 stored fields; this is 63 over it, 3.10× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: SessionConfig src/common/src/session_config/mod.rs:101— TooManyFields — 85 stored fields beside 3 methods. The bar is 30 stored fields; this is 55 over it, 2.83× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: MetaConfig src/common/src/config/meta.rs:133— TooManyFields — 71 stored fields. The bar is 30 stored fields; this is 41 over it, 2.37× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: StorageConfig src/common/src/config/storage.rs:23— TooManyFields — 67 stored fields. The bar is 30 stored fields; this is 37 over it, 2.23× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: StreamingDeveloperConfig src/common/src/config/streaming.rs:82— TooManyFields — 58 stored fields beside 1 method. The bar is 30 stored fields; this is 28 over it, 1.93× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: HummockStateStoreMetrics src/storage/src/monitor/hummock_state_store_metrics.rs:43— TooManyFields — 45 stored fields beside 2 methods. The bar is 30 stored fields; this is 15 over it, 1.50× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: NexmarkProperties src/connector/src/source/nexmark/mod.rs:50— TooManyFields — 44 stored fields. The bar is 30 stored fields; this is 14 over it, 1.47× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: TableCatalog src/frontend/src/catalog/table_catalog.rs:83— TooManyFields — 43 stored fields beside 49 methods. The bar is 30 stored fields; this is 13 over it, 1.43× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: IcebergCommon src/connector/src/connector_common/iceberg/mod.rs:57— TooManyFields — 41 stored fields beside 19 methods. The bar is 30 stored fields; this is 11 over it, 1.37× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: MetadataV2 src/storage/backup/src/meta_snapshot_v2.rs:89— TooManyFields — 38 stored fields. The bar is 30 stored fields; this is 8 over it, 1.27× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: IcebergConfig src/connector/src/sink/iceberg/config.rs:297— TooManyFields — 36 stored fields beside 24 methods. The bar is 30 stored fields; this is 6 over it, 1.20× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: Model src/meta/model/src/table.rs:185— TooManyFields — 35 stored fields beside 1 method. The bar is 30 stored fields; this is 5 over it, 1.17× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
TooManyFields: MetaNodeOpts src/meta/node/src/lib.rs:45— TooManyFields — 33 stored fields. The bar is 30 stored fields; this is 3 over it, 1.10× the bar. This is width in DATA, not behaviour: every reader that takes the whole type couples to all of its fields, so a change to any one of them is a change every reader has to be checked against. To reduce it, group the fields that are read together by the same callers into a smaller type of their own, and have this one hold that type as a single member — each reader then names only the group it uses.
risingwave_storage::hummock::compactor::start_iceberg_compactor (cognitive 119) src/storage/src/hummock/compactor/mod.rs:400— risingwave_storage::hummock::compactor::start_iceberg_compactor has cognitive complexity 119 (threshold 15). Drivers by points: if/else 17 (75 pts), match/switch 9 (34 pts), loops 3 (8 pts), boolean chains 2 (nesting depth added 88). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::compactor::start_compactor (cognitive 84) src/storage/src/hummock/compactor/mod.rs:951— risingwave_storage::hummock::compactor::start_compactor has cognitive complexity 84 (threshold 15). Drivers by points: if/else 10 (43 pts), match/switch 9 (36 pts), loops 2 (3 pts), boolean chains 2 (nesting depth added 61). Of this number, 81 points are the body's own statements and 3 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::compactor::iceberg_compaction::memory::estimate_plan_memory (cognitive 48) src/storage/src/hummock/compactor/iceberg_compaction/memory.rs:59— risingwave_storage::hummock::compactor::iceberg_compaction::memory::estimate_plan_memory has cognitive complexity 48 (threshold 15). Drivers by points: if/else 41 (43 pts), boolean chains 2, match/switch 1 (2 pts), loops 1 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
risingwave_storage::hummock::compactor::start_shared_compactor (cognitive 44) src/storage/src/hummock/compactor/mod.rs:1320— risingwave_storage::hummock::compactor::start_shared_compactor has cognitive complexity 44 (threshold 15). Drivers by points: match/switch 7 (28 pts), if/else 3 (13 pts), boolean chains 2, loops 1 (nesting depth added 31). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_storage::hummock::compactor::compactor_runner::compact_and_build_sst (cognitive 43) src/storage/src/hummock/compactor/compactor_runner.rs:758— risingwave_storage::hummock::compactor::compactor_runner::compact_and_build_sst has cognitive complexity 43 (threshold 15). Drivers by points: if/else 17 (33 pts), boolean chains 6, match/switch 1 (3 pts), loops 1 (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::local_version::pinned_version::start_pinned_version_worker (cognitive 38) src/storage/src/hummock/local_version/pinned_version.rs:197— risingwave_storage::hummock::local_version::pinned_version::start_pinned_version_worker has cognitive complexity 38 (threshold 15). Drivers by points: match/switch 6 (19 pts), if/else 4 (11 pts), loops 4 (7 pts), boolean chains 1 (nesting depth added 23). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_storage::hummock::compactor::shared_buffer_compact::compact_shared_buffer (cognitive 32) src/storage/src/hummock/compactor/shared_buffer_compact.rs:145— risingwave_storage::hummock::compactor::shared_buffer_compact::compact_shared_buffer has cognitive complexity 32 (threshold 15). Drivers by points: if/else 10 (15 pts), loops 6 (12 pts), match/switch 2 (5 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::compactor::iceberg_compaction::iceberg_compactor_runner::build_task_planning_config (cognitive 26) src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:756— risingwave_storage::hummock::compactor::iceberg_compaction::iceberg_compactor_runner::build_task_planning_config has cognitive complexity 26 (threshold 15). Drivers by points: if/else 12 (20 pts), match/switch 3 (4 pts), boolean chains 2 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::compactor::compactor_runner::compact_with_agent (cognitive 23) src/storage/src/hummock/compactor/compactor_runner.rs:323— risingwave_storage::hummock::compactor::compactor_runner::compact_with_agent has cognitive complexity 23 (threshold 15). Drivers by points: match/switch 6 (14 pts), if/else 5, loops 3 (4 pts) (nesting depth added 9). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_storage::hummock::utils::filter_with_delete_range (cognitive 22) src/storage/src/hummock/utils.rs:539— risingwave_storage::hummock::utils::filter_with_delete_range has cognitive complexity 22 (threshold 15). Drivers by points: if/else 11 (19 pts), loops 1 (3 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::compactor::shared_buffer_compact::generate_splits (cognitive 20) src/storage/src/hummock/compactor/shared_buffer_compact.rs:330— risingwave_storage::hummock::compactor::shared_buffer_compact::generate_splits has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (11 pts), loops 3 (5 pts), boolean chains 4 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::validator::validate_ssts (cognitive 20) src/storage/src/hummock/validator.rs:32— risingwave_storage::hummock::validator::validate_ssts has cognitive complexity 20 (threshold 15). Drivers by points: if/else 5 (15 pts), loops 2 (3 pts), match/switch 1 (2 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::utils::merge_stream (cognitive 20) src/storage/src/hummock/utils.rs:785— risingwave_storage::hummock::utils::merge_stream has cognitive complexity 20 (threshold 15). Drivers by points: match/switch 5 (16 pts), if/else 1 (3 pts), loops 1 (nesting depth added 13). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_storage::hummock::compactor::iterator::filter_block_metas (cognitive 18) src/storage/src/hummock/compactor/iterator.rs:541— risingwave_storage::hummock::compactor::iterator::filter_block_metas has cognitive complexity 18 (threshold 15). Drivers by points: if/else 11 (16 pts), loops 2 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_storage::hummock::compactor::compaction_utils::generate_splits (cognitive 16) src/storage/src/hummock/compactor/compaction_utils.rs:244— risingwave_storage::hummock::compactor::compaction_utils::generate_splits has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (10 pts), loops 2 (5 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::drop_object (cognitive 51) src/meta/src/controller/catalog/drop_op.rs:24— CatalogController::drop_object has cognitive complexity 51 (threshold 15). Drivers by points: if/else 15 (28 pts), loops 6 (10 pts), boolean chains 7, match/switch 5 (6 pts) (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::update_connection_and_dependent_objects_props (cognitive 43) src/meta/src/controller/streaming_job.rs:3280— CatalogController::update_connection_and_dependent_objects_props has cognitive complexity 43 (threshold 15). Drivers by points: if/else 12 (24 pts), loops 8 (14 pts), match/switch 1 (3 pts), boolean chains 2 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::grant_default_privileges (cognitive 43) src/meta/src/controller/user.rs:520— CatalogController::grant_default_privileges has cognitive complexity 43 (threshold 15). Drivers by points: loops 10 (26 pts), if/else 7 (16 pts), boolean chains 1 (nesting depth added 25). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
CatalogController::clean_dirty_sink_downstreams (cognitive 32) src/meta/src/controller/catalog/util.rs:509— CatalogController::clean_dirty_sink_downstreams has cognitive complexity 32 (threshold 15). Drivers by points: if/else 8 (24 pts), loops 3 (4 pts), match/switch 1 (4 pts) (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::try_abort_creating_streaming_job (cognitive 32) src/meta/src/controller/streaming_job.rs:1022— CatalogController::try_abort_creating_streaming_job has cognitive complexity 32 (threshold 15). Drivers by points: if/else 17 (24 pts), loops 3 (5 pts), boolean chains 3 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::create_job_catalog (cognitive 30) src/meta/src/controller/streaming_job.rs:467— CatalogController::create_job_catalog has cognitive complexity 30 (threshold 15). Drivers by points: if/else 14 (22 pts), match/switch 3 (5 pts), boolean chains 3 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::finish_replace_streaming_job_inner (cognitive 28) src/meta/src/controller/streaming_job.rs:2034— CatalogController::finish_replace_streaming_job_inner has cognitive complexity 28 (threshold 15). Drivers by points: if/else 8 (13 pts), loops 6 (10 pts), boolean chains 3, match/switch 2 (nesting depth added 9). Of this number, 21 points are the body's own statements and 7 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::update_fragment_rate_limit_by_fragment_id (cognitive 27) src/meta/src/controller/streaming_job.rs:3747— CatalogController::update_fragment_rate_limit_by_fragment_id has cognitive complexity 27 (threshold 15). Drivers by points: if/else 7 (18 pts), match/switch 4 (9 pts) (nesting depth added 16). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
CatalogController::revoke_privilege (cognitive 27) src/meta/src/controller/user.rs:340— CatalogController::revoke_privilege has cognitive complexity 27 (threshold 15). Drivers by points: if/else 13 (21 pts), loops 4 (5 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::alter_owner (cognitive 21) src/meta/src/controller/catalog/alter_op.rs:281— CatalogController::alter_owner has cognitive complexity 21 (threshold 15). Drivers by points: if/else 7 (13 pts), loops 2 (6 pts), boolean chains 1, match/switch 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::get_table_change_log_truncate_info (cognitive 20) src/meta/src/controller/streaming_job.rs:242— CatalogController::get_table_change_log_truncate_info has cognitive complexity 20 (threshold 15). Drivers by points: if/else 4 (11 pts), match/switch 2 (6 pts), loops 2 (3 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::clean_dirty_creating_jobs (cognitive 17) src/meta/src/controller/catalog/mod.rs:637— CatalogController::clean_dirty_creating_jobs has cognitive complexity 17 (threshold 15). Drivers by points: if/else 8, match/switch 3 (5 pts), boolean chains 4 (nesting depth added 2). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
CatalogController::grant_privilege (cognitive 17) src/meta/src/controller/user.rs:224— CatalogController::grant_privilege has cognitive complexity 17 (threshold 15). Drivers by points: if/else 5 (11 pts), loops 4 (6 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CatalogController::post_collect_job_fragments (cognitive 16) src/meta/src/controller/streaming_job.rs:1329— CatalogController::post_collect_job_fragments has cognitive complexity 16 (threshold 15). Drivers by points: if/else 11 (13 pts), match/switch 2 (3 pts) (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
CatalogController::finish_streaming_job_inner (cognitive 16) src/meta/src/controller/streaming_job.rs:1724— CatalogController::finish_streaming_job_inner has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (8 pts), loops 2 (7 pts), match/switch 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (18 lines × 2) src/connector/src/sink/batching_log_sink.rs:67— src/connector/src/sink/batching_log_sink.rs:67-84 | src/connector/src/sink/writer.rs:150-167 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (18 lines × 2) src/expr/impl/src/scalar/jsonb_delete.rs:352— src/expr/impl/src/scalar/jsonb_delete.rs:352-369 | src/expr/impl/src/scalar/jsonb_set.rs:114-131 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (18 lines × 2) src/frontend/src/metrics_reader.rs:108— src/frontend/src/metrics_reader.rs:108-125 | src/frontend/src/metrics_reader.rs:137-154 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/frontend/src/handler/create_function.rs:118— src/frontend/src/handler/create_function.rs:118-135 | src/frontend/src/handler/create_sql_function.rs:100-117 — before extracting anything, compare `src/frontend/src/handler/create_function.rs` and `src/frontend/src/handler/create_sql_function.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (18 lines × 2) src/meta/service/src/hummock_service.rs:440— src/meta/service/src/hummock_service.rs:440-457 | src/meta/service/src/hummock_service.rs:492-509 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/meta/src/barrier/checkpoint/state.rs:524— src/meta/src/barrier/checkpoint/state.rs:524-541 | src/meta/src/barrier/checkpoint/state.rs:857-874 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/meta/src/dashboard/mod.rs:702— src/meta/src/dashboard/mod.rs:702-719 | src/meta/src/dashboard/mod.rs:785-802 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/meta/src/dashboard/mod.rs:726— src/meta/src/dashboard/mod.rs:726-743 | src/meta/src/dashboard/mod.rs:807-824 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:294— src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:294-311 | src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:862-879 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/storage/src/hummock/iterator/skip_watermark.rs:206— src/storage/src/hummock/iterator/skip_watermark.rs:206-223 | src/storage/src/hummock/iterator/skip_watermark.rs:566-583 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/stream/src/executor/over_window/over_partition.rs:1047— src/stream/src/executor/over_window/over_partition.rs:1047-1064 | src/stream/src/executor/over_window/over_partition.rs:1091-1108 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2) src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:76— src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:76-93 | src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs:209-226 — before extracting anything, compare `src/stream/src/executor/source/batch_source/batch_iceberg_list.rs` and `src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 45 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (18 lines × 2) src/batch/executors/src/executor/hash_agg.rs:690— src/batch/executors/src/executor/hash_agg.rs:690-707 | src/batch/executors/src/executor/join/hash_join.rs:676-693 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/join/hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 81 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (18 lines × 2) e2e_test/udf/remote_java/src/main/java/com/example/UdfExample.java:235— e2e_test/udf/remote_java/src/main/java/com/example/UdfExample.java:235-252 | e2e_test/udf/remote_java/src/main/java/com/example/UdfExample.java:299-316 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. Each matched range is the entire body of the declaration above it, so the region is already a complete unit: move that whole declaration to the shared location and have each site call it, rather than lifting the lines out of their bodies. Any `return` inside it is the body's own exit and keeps its meaning in the moved unit.
Duplicated block (18 lines × 2) e2e_test/s3/file_source.py:332— e2e_test/s3/file_source.py:332-349 | e2e_test/s3/file_source.py:449-466 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Repeated repair: src/meta/src/barrier/schedule.rs src/meta/src/barrier/schedule.rs:635— src/meta/src/barrier/schedule.rs changed 12 times in last 90 days and 7 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 13 (its worst body is ScheduledBarriers::mark_ready at line 635), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(refresh): finish a table refresh only after all materialize actors and abandon it on recovery (#27041)”; “fix(stream): derive NOW progress from elapsed time (#27209)”; “fix(meta): fence sink coordinators during recovery (#27180)”; “fix(stream): use database barrier interval for now (#27118)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/schedule.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/node/src/lib.rs src/meta/node/src/lib.rs:607— src/meta/node/src/lib.rs changed 10 times in last 90 days and 6 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 8 (its worst body is risingwave_meta_node::validate_config at line 607), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(meta): stabilize automatic compaction group split and merge (#27044)”; “fix(meta): handle incoming sinks in table drops and ALTER MV concurrency checks (#26667)”; “fix(meta): preserve recoverable foreground jobs after recovery (#26472)”; “fix(meta): throttle snapshot backfill catch-up barriers (#26423)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/node/src/lib.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/src/manager/env.rs src/meta/src/manager/env.rs:424— src/meta/src/manager/env.rs changed 7 times in last 90 days and 6 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 3 (its worst body is MetaSrvEnv::new at line 424), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(meta): stabilize automatic compaction group split and merge (#27044)”; “fix(meta): handle incoming sinks in table drops and ALTER MV concurrency checks (#26667)”; “fix(meta): preserve recoverable foreground jobs after recovery (#26472)”; “fix(meta): limit pending barriers in partial graphs (#26467)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/manager/env.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/src/controller/catalog/mod.rs src/meta/src/controller/catalog/mod.rs:637— src/meta/src/controller/catalog/mod.rs changed 9 times in last 90 days and 5 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 12 (its worst body is CatalogController::clean_dirty_creating_jobs at line 637), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(meta): preserve recoverable foreground jobs after recovery (#26472)”; “fix(meta): unify creating job catalog notifications (#26557)”; “fix(meta): notify hummock for cache refill config (#26464)”; “fix(meta): reconcile stale serving vnode mappings (#26352)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/controller/catalog/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/src/barrier/context/recovery.rs src/meta/src/barrier/context/recovery.rs:727— src/meta/src/barrier/context/recovery.rs changed 7 times in last 90 days and 4 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 11 (its worst body is GlobalBarrierWorkerContextImpl::resolve_hummock_version_epochs at line 727), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(refresh): finish a table refresh only after all materialize actors and abandon it on recovery (#27041)”; “fix(meta): fence sink coordinators during recovery (#27180)”; “fix(meta): preserve recoverable foreground jobs after recovery (#26472)”; “fix(meta): clear iceberg maintenance for user-created sinks on cascade drop (#26228)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/context/recovery.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/src/barrier/manager.rs src/meta/src/barrier/manager.rs:164— src/meta/src/barrier/manager.rs changed 7 times in last 90 days and 4 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 4 (its worst body is GlobalBarrierManager::check_status_running at line 164), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(refresh): finish a table refresh only after all materialize actors and abandon it on recovery (#27041)”; “fix(meta): preserve recoverable foreground jobs after recovery (#26472)”; “fix(stream): handle cross-db backfill creation stalls (#26119)”; “fix(meta): clear iceberg maintenance for user-created sinks on cascade drop (#26228)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/manager.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/src/barrier/checkpoint/independent_job/creating_job/status.rs src/meta/src/barrier/checkpoint/independent_job/creating_job/status.rs:138— src/meta/src/barrier/checkpoint/independent_job/creating_job/status.rs changed 7 times in last 90 days and 4 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 7 (its worst body is CreatingStreamingJobStatus::update_progress at line 138), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(stream): derive NOW progress from elapsed time (#27209)”; “fix(stream): use database barrier interval for now (#27118)”; “fix(meta): limit pending barriers in partial graphs (#26467)”; “fix(meta): throttle snapshot backfill catch-up barriers (#26423)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/checkpoint/independent_job/creating_job/status.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/connector/src/source/cdc/external/mod.rs src/connector/src/source/cdc/external/mod.rs:61— src/connector/src/source/cdc/external/mod.rs changed 6 times in last 90 days and 4 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 6 (its worst body is ExternalCdcTableType::from_properties at line 61), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(stream): preserve CDC events during recovery startup (#27031)”; “fix(cdc): diagnose postgres select privilege (#26079)”; “fix(cdc): fail initial backfill on invalid primary keys (#26513)”; “fix(mysql-cdc): compare unsigned pk with unsigned semantics in backfill buffer (#25947)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/connector/src/source/cdc/external/mod.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/storage/src/hummock/sstable/forward_sstable_iterator.rs src/storage/src/hummock/sstable/forward_sstable_iterator.rs:65— src/storage/src/hummock/sstable/forward_sstable_iterator.rs changed 5 times in last 90 days and 4 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 10 (its worst body is SstableIterator::new at line 65), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(storage): handle exhausted prefetch streams during seek (#27161)”; “fix(storage): bound SST scans and point gets by table ID (#27048)”; “fix(storage): collect point get iterator stats (#26405)”; “fix(storage): enforce scan range in forward SST iterator (#26480)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/storage/src/hummock/sstable/forward_sstable_iterator.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/src/barrier/checkpoint/recovery.rs src/meta/src/barrier/checkpoint/recovery.rs:184— src/meta/src/barrier/checkpoint/recovery.rs changed 4 times in last 90 days and 4 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 7 (its worst body is DatabaseRecoveringState::poll_next_event at line 184), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(stream): derive NOW progress from elapsed time (#27209)”; “fix(meta): fence sink coordinators during recovery (#27180)”; “fix(stream): use database barrier interval for now (#27118)”; “fix(meta): preserve recoverable foreground jobs after recovery (#26472)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/barrier/checkpoint/recovery.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/common/src/config/meta.rs src/common/src/config/meta.rs:97— src/common/src/config/meta.rs changed 4 times in last 90 days and 3 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 3 (its worst body is DefaultParallelism::deserialize at line 97), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(meta): stabilize automatic compaction group split and merge (#27044)”; “fix(meta): handle incoming sinks in table drops and ALTER MV concurrency checks (#26667)”; “fix(meta): preserve recoverable foreground jobs after recovery (#26472)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/common/src/config/meta.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/meta/src/hummock/manager/timer_task.rs src/meta/src/hummock/manager/timer_task.rs:595— src/meta/src/hummock/manager/timer_task.rs changed 4 times in last 90 days and 3 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 12 (its worst body is HummockManager::check_dead_task at line 595), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(meta): stabilize automatic compaction group split and merge (#27044)”; “fix(meta): preserve compaction candidates across topology changes (#27042)”; “fix(meta): don't panic on hummock timer child cancellation during shutdown (#26221)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/meta/src/hummock/manager/timer_task.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/common/src/config/streaming.rs src/common/src/config/streaming.rs:373— src/common/src/config/streaming.rs changed 4 times in last 90 days and 3 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 3 (its worst body is StreamingConfig::unrecognized_keys at line 373), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(meta): limit pending barriers in partial graphs (#26467)”; “fix(meta): throttle snapshot backfill catch-up barriers (#26423)”; “fix(meta): gate snapshot backfill merge on pending barriers (#26288)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/common/src/config/streaming.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
Repeated repair: src/utils/pgwire/src/pg_server.rs src/utils/pgwire/src/pg_server.rs:325— src/utils/pgwire/src/pg_server.rs changed 3 times in last 90 days and 3 of those changes were fix/bug commits, so repair is the majority of this file's churn. Its max cyclomatic complexity is 6 (its worst body is UserAuthenticator::authenticate at line 325), UNDER the 15 threshold, so this is deliberately not filed as a churn × complexity hotspot — the difficulty here is in the behaviour the file has to get right, not in its control flow, and refactoring it for complexity would be the wrong move. The repairs counted were: “fix(pgwire): stream query results incrementally (#26727)”; “fix(pgwire): support configurable OAuth audience (#26531)”; “fix(pgwire): tolerate mixed-key JWKS for OAuth (#26416)”. Each one is a case this code did not handle. Before the next change lands here, check that every one of them is pinned by a test that fails without its fix; where the same area keeps coming back, the durable fix is usually at the interface that keeps being misused rather than at the line that was last corrected. Counted over 2026-06-30..2026-09-28, the 90 days ending at the analysed commit. Reproduce with `git log --since='2026-06-30 12:28:15 +00:00' --until='2026-09-28 12:28:15 +00:00' --full-history --no-merges -- src/utils/pgwire/src/pg_server.rs`: merges are excluded because a merge re-states changes already counted at their own commits, and history is NOT path-simplified because a change that reached the file through a merged branch is still a change to it. That command counts raw commits and can read HIGHER than this row, which counts a cherry-picked re-land, and a revert together with the commit it undoes, once each — a difference of several commits on a file whose history was re-landed or reverted inside the window.
HashJoinExecutor::do_execute (cognitive 72) src/batch/executors/src/executor/join/hash_join.rs:478— HashJoinExecutor::do_execute has cognitive complexity 72 (threshold 15). Drivers by points: if/else 14 (35 pts), loops 11 (27 pts), match/switch 3 (7 pts), boolean chains 3 (nesting depth added 41). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
HashJoinExecutor::do_left_outer_join (cognitive 46) src/batch/executors/src/executor/join/hash_join.rs:857— HashJoinExecutor::do_left_outer_join has cognitive complexity 46 (threshold 15). Drivers by points: if/else 11 (38 pts), loops 3 (8 pts) (nesting depth added 32). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
HashJoinExecutor::handle_watermark (cognitive 33) src/stream/src/executor/hash_join.rs:815— HashJoinExecutor::handle_watermark has cognitive complexity 33 (threshold 15). Drivers by points: if/else 10 (20 pts), loops 4 (10 pts), boolean chains 3 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::handle_match_rows (cognitive 29) src/stream/src/executor/hash_join.rs:1087— HashJoinExecutor::handle_match_rows has cognitive complexity 29 (threshold 15). Drivers by points: if/else 9 (17 pts), loops 3 (5 pts), match/switch 4 (5 pts), boolean chains 2 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::do_inner_join (cognitive 26) src/batch/executors/src/executor/join/hash_join.rs:777— HashJoinExecutor::do_inner_join has cognitive complexity 26 (threshold 15). Drivers by points: if/else 6 (19 pts), loops 3 (7 pts) (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::handle_match_row (cognitive 25) src/stream/src/executor/hash_join.rs:1264— HashJoinExecutor::handle_match_row has cognitive complexity 25 (threshold 15). Drivers by points: if/else 9 (16 pts), match/switch 1 (4 pts), boolean chains 3, loops 1 (2 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::do_left_outer_join_with_non_equi_condition (cognitive 22) src/batch/executors/src/executor/join/hash_join.rs:947— HashJoinExecutor::do_left_outer_join_with_non_equi_condition has cognitive complexity 22 (threshold 15). Drivers by points: if/else 6 (15 pts), loops 3 (7 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::do_full_outer_join_with_non_equi_condition (cognitive 22) src/batch/executors/src/executor/join/hash_join.rs:1558— HashJoinExecutor::do_full_outer_join_with_non_equi_condition has cognitive complexity 22 (threshold 15). Drivers by points: if/else 5 (14 pts), loops 4 (8 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::find_asof_matched_rows (cognitive 22) src/batch/executors/src/executor/join/hash_join.rs:2001— HashJoinExecutor::find_asof_matched_rows has cognitive complexity 22 (threshold 15). Drivers by points: if/else 6 (15 pts), match/switch 1 (4 pts), loops 1 (2 pts), boolean chains 1 (nesting depth added 13). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
HashJoinExecutor::do_left_semi_join_with_non_equi_condition (cognitive 21) src/batch/executors/src/executor/join/hash_join.rs:1091— HashJoinExecutor::do_left_semi_join_with_non_equi_condition has cognitive complexity 21 (threshold 15). Drivers by points: if/else 4 (14 pts), loops 3 (7 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::do_full_outer_join (cognitive 21) src/batch/executors/src/executor/join/hash_join.rs:1489— HashJoinExecutor::do_full_outer_join has cognitive complexity 21 (threshold 15). Drivers by points: if/else 4 (13 pts), loops 4 (8 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::into_stream (cognitive 21) src/stream/src/executor/hash_join.rs:584— HashJoinExecutor::into_stream has cognitive complexity 21 (threshold 15). Drivers by points: loops 6 (16 pts), if/else 1 (3 pts), match/switch 1 (2 pts) (nesting depth added 13). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
HashJoinExecutor::eq_join_oneside (cognitive 20) src/stream/src/executor/hash_join.rs:949— HashJoinExecutor::eq_join_oneside has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (10 pts), loops 3 (7 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashJoinExecutor::do_left_anti_join_with_non_equi_condition (cognitive 18) src/batch/executors/src/executor/join/hash_join.rs:1162— HashJoinExecutor::do_left_anti_join_with_non_equi_condition has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (11 pts), loops 3 (7 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::temporal_join::phase1::handle_chunk (cognitive 69) src/stream/src/executor/temporal_join.rs:448— risingwave_stream::executor::temporal_join::phase1::handle_chunk has cognitive complexity 69 (threshold 15). Drivers by points: if/else 15 (41 pts), loops 5 (19 pts), match/switch 3 (7 pts), boolean chains 2 (nesting depth added 44). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::barrier_align::barrier_align (cognitive 44) src/stream/src/executor/barrier_align.rs:45— risingwave_stream::executor::barrier_align::barrier_align has cognitive complexity 44 (threshold 15). Drivers by points: match/switch 8 (26 pts), loops 5 (15 pts), if/else 2 (3 pts) (nesting depth added 29). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_stream::executor::lookup::sides::align_barrier (cognitive 36) src/stream/src/executor/lookup/sides.rs:124— risingwave_stream::executor::lookup::sides::align_barrier has cognitive complexity 36 (threshold 15). Drivers by points: match/switch 7 (19 pts), loops 6 (17 pts) (nesting depth added 23). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_stream::executor::backfill::snapshot_backfill::executor::make_consume_snapshot_stream (cognitive 32) src/stream/src/executor/backfill/snapshot_backfill/executor.rs:1015— risingwave_stream::executor::backfill::snapshot_backfill::executor::make_consume_snapshot_stream has cognitive complexity 32 (threshold 15). Drivers by points: if/else 10 (25 pts), match/switch 2 (3 pts), boolean chains 2, loops 2 (nesting depth added 16). Of this number, 30 points are the body's own statements and 2 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::lookup::sides::stream_lookup_arrange_this_epoch (cognitive 31) src/stream/src/executor/lookup/sides.rs:299— risingwave_stream::executor::lookup::sides::stream_lookup_arrange_this_epoch has cognitive complexity 31 (threshold 15). Drivers by points: loops 6 (18 pts), match/switch 4 (13 pts) (nesting depth added 21). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_stream::common::log_store_impl::kv_log_store::serde::stream_de::may_merge_update (cognitive 29) src/stream/src/common/log_store_impl/kv_log_store/serde.rs:792— risingwave_stream::common::log_store_impl::kv_log_store::serde::stream_de::may_merge_update has cognitive complexity 29 (threshold 15). Drivers by points: if/else 11 (28 pts), loops 1 (nesting depth added 17). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
risingwave_stream::executor::exchange::input::remote_input::run_inner (cognitive 21) src/stream/src/executor/exchange/input.rs:239— risingwave_stream::executor::exchange::input::remote_input::run_inner has cognitive complexity 21 (threshold 15). Drivers by points: if/else 3 (8 pts), match/switch 3 (8 pts), loops 2 (5 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::from_proto::source::trad_source::create_source_desc_builder (cognitive 19) src/stream/src/from_proto/source/trad_source.rs:43— risingwave_stream::from_proto::source::trad_source::create_source_desc_builder has cognitive complexity 19 (threshold 15). Drivers by points: if/else 5 (13 pts), boolean chains 4, loops 1 (2 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::over_window::frame_finder::find_curr_for_rows_frame (cognitive 18) src/stream/src/executor/over_window/frame_finder.rs:219— risingwave_stream::executor::over_window::frame_finder::find_curr_for_rows_frame has cognitive complexity 18 (threshold 15). Drivers by points: if/else 14 (17 pts), loops 1 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
risingwave_stream::executor::temporal_join::align_input (cognitive 18) src/stream/src/executor/temporal_join.rs:263— risingwave_stream::executor::temporal_join::align_input has cognitive complexity 18 (threshold 15). Drivers by points: if/else 2 (8 pts), loops 3 (7 pts), match/switch 1 (3 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::lookup::sides::stream_lookup_arrange_prev_epoch (cognitive 16) src/stream/src/executor/lookup/sides.rs:215— risingwave_stream::executor::lookup::sides::stream_lookup_arrange_prev_epoch has cognitive complexity 16 (threshold 15). Drivers by points: match/switch 2 (6 pts), if/else 2 (5 pts), loops 3 (5 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::iceberg_with_pk_index::compaction_resolver::collect_input_dvs (cognitive 16) src/stream/src/executor/iceberg_with_pk_index/compaction_resolver.rs:324— risingwave_stream::executor::iceberg_with_pk_index::compaction_resolver::collect_input_dvs has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (12 pts), loops 2 (3 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::dispatch::try_batch_barriers (cognitive 16) src/stream/src/executor/dispatch.rs:580— risingwave_stream::executor::dispatch::try_batch_barriers has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (14 pts), loops 1, match/switch 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_stream::executor::iceberg_with_pk_index::position_delete_handler_impl::seed_from_delete_manifests (cognitive 16) src/stream/src/executor/iceberg_with_pk_index/position_delete_handler_impl.rs:286— risingwave_stream::executor::iceberg_with_pk_index::position_delete_handler_impl::seed_from_delete_manifests has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 2 (3 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (17 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:1325— src/batch/executors/src/executor/join/hash_join.rs:1325-1341 | src/batch/executors/src/executor/join/hash_join.rs:1442-1458 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17 lines × 2) src/batch/src/task/consistent_hash_shuffle_channel.rs:118— src/batch/src/task/consistent_hash_shuffle_channel.rs:118-134 | src/batch/src/task/hash_shuffle_channel.rs:114-130 — before extracting anything, compare `src/batch/src/task/consistent_hash_shuffle_channel.rs` and `src/batch/src/task/hash_shuffle_channel.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (17 lines × 2) src/frontend/src/datafusion/aggregate/single_phase.rs:331— src/frontend/src/datafusion/aggregate/single_phase.rs:331-347 | src/frontend/src/datafusion/aggregate/two_phase.rs:304-320 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (17 lines × 2) src/frontend/src/expr/table_function.rs:296— src/frontend/src/expr/table_function.rs:296-312 | src/frontend/src/expr/table_function.rs:383-399 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17 lines × 2) src/frontend/src/optimizer/rule/table_function_to_mysql_query_rule.rs:44— src/frontend/src/optimizer/rule/table_function_to_mysql_query_rule.rs:44-60 | src/frontend/src/optimizer/rule/table_function_to_postgres_query_rule.rs:45-61 — before extracting anything, compare `src/frontend/src/optimizer/rule/table_function_to_mysql_query_rule.rs` and `src/frontend/src/optimizer/rule/table_function_to_postgres_query_rule.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 42 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (17 lines × 2) src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs:282— src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs:282-298 | src/meta/src/barrier/checkpoint/state.rs:358-374 — before extracting anything, compare `src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs` and `src/meta/src/barrier/checkpoint/state.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 52 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (17 lines × 2) src/meta/src/barrier/checkpoint/state.rs:564— src/meta/src/barrier/checkpoint/state.rs:564-580 | src/meta/src/barrier/checkpoint/state.rs:699-715 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17 lines × 2) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:336— src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:336-352 | src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:915-931 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17 lines × 2) src/storage/src/hummock/iterator/mod.rs:398— src/storage/src/hummock/iterator/mod.rs:398-414 | src/storage/src/hummock/iterator/mod.rs:436-452 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17 lines × 2) src/stream/src/executor/asof_join.rs:553— src/stream/src/executor/asof_join.rs:553-569 | src/stream/src/executor/hash_join.rs:851-867 — before extracting anything, compare `src/stream/src/executor/asof_join.rs` and `src/stream/src/executor/hash_join.rs` as WHOLE FILES: this scan already matched 13 separate duplicated blocks between them, totalling at least 244 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (17 lines × 2) src/stream/src/executor/join/asof_join.rs:480— src/stream/src/executor/join/asof_join.rs:480-496 | src/stream/src/executor/join/asof_join.rs:540-556 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17 lines × 2) src/stream/src/executor/project/project_scalar.rs:339— src/stream/src/executor/project/project_scalar.rs:339-355 | src/stream/src/executor/project/project_set.rs:132-148 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (17 lines × 2) src/stream/src/executor/top_n/group_top_n.rs:180— src/stream/src/executor/top_n/group_top_n.rs:180-196 | src/stream/src/executor/top_n/group_top_n_appendonly.rs:163-179 — before extracting anything, compare `src/stream/src/executor/top_n/group_top_n.rs` and `src/stream/src/executor/top_n/group_top_n_appendonly.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 69 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (17 lines × 2) src/utils/pgwire/src/ldap_auth.rs:240— src/utils/pgwire/src/ldap_auth.rs:240-256 | src/utils/pgwire/src/ldap_auth.rs:344-360 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10 lines × 3) src/batch/executors/src/executor/join/hash_join.rs:989— src/batch/executors/src/executor/join/hash_join.rs:989-998 | src/batch/executors/src/executor/join/hash_join.rs:1199-1208 | src/batch/executors/src/executor/join/hash_join.rs:1607-1616 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) src/batch/executors/src/executor/join/hash_join.rs:1333— src/batch/executors/src/executor/join/hash_join.rs:1333-1342 | src/batch/executors/src/executor/join/hash_join.rs:1450-1459 | src/batch/executors/src/executor/join/hash_join.rs:1605-1614 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) src/batch/executors/src/executor/join/nested_loop_join.rs:256— src/batch/executors/src/executor/join/nested_loop_join.rs:256-268 | src/batch/executors/src/executor/join/nested_loop_join.rs:382-391 | src/batch/executors/src/executor/join/nested_loop_join.rs:426-435 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) src/batch/executors/src/executor/sort_over_window.rs:63— src/batch/executors/src/executor/sort_over_window.rs:63-72 | src/stream/src/from_proto/eowc_over_window.rs:40-49 | src/stream/src/from_proto/over_window.rs:42-51 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (10 lines × 3) src/connector/src/parser/unified/debezium.rs:750— src/connector/src/parser/unified/debezium.rs:750-759 | src/connector/src/parser/unified/debezium.rs:815-824 | src/connector/src/parser/unified/debezium.rs:1187-1196 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) src/frontend/src/catalog/system_catalog/mod.rs:245— src/frontend/src/catalog/system_catalog/mod.rs:245-254 | src/meta/src/controller/fragment.rs:1573-1582 | src/meta/src/manager/diagnose.rs:1264-1273 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (10 lines × 3) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:245— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:245-254 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:330-339 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:475-484 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) src/frontend/src/handler/alter_owner.rs:89— src/frontend/src/handler/alter_owner.rs:89-98 | src/frontend/src/handler/alter_owner.rs:134-143 | src/frontend/src/handler/alter_owner.rs:151-160 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) src/frontend/src/handler/alter_owner.rs:122— src/frontend/src/handler/alter_owner.rs:122-131 | src/frontend/src/handler/alter_owner.rs:139-148 | src/frontend/src/handler/alter_owner.rs:156-165 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) src/meta/model/migration/src/m20240304_074901_subscription.rs:13— src/meta/model/migration/src/m20240304_074901_subscription.rs:13-22 | src/meta/model/migration/src/m20240506_112555_subscription_partial_ckpt.rs:14-23 | src/meta/model/migration/src/m20240506_112555_subscription_partial_ckpt.rs:64-73 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (10 lines × 3) src/batch/src/task/broadcast_channel.rs:57— src/batch/src/task/broadcast_channel.rs:57-66 | src/batch/src/task/consistent_hash_shuffle_channel.rs:136-145 | src/batch/src/task/hash_shuffle_channel.rs:132-141 — before extracting anything, compare `src/batch/src/task/consistent_hash_shuffle_channel.rs` and `src/batch/src/task/hash_shuffle_channel.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 3) src/frontend/src/expr/type_inference/func.rs:493— src/frontend/src/expr/type_inference/func.rs:493-502 | src/frontend/src/expr/type_inference/func.rs:506-515 | src/frontend/src/expr/type_inference/func.rs:519-528 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 3) integration_tests/feature-store/server/src/model.rs:187— integration_tests/feature-store/server/src/model.rs:187-196 | integration_tests/feature-store/server/src/server_pb.rs:366-375 | integration_tests/feature-store/simulator/src/server_pb.rs:366-375 — before extracting anything, compare `integration_tests/feature-store/server/src/model.rs` and `integration_tests/feature-store/server/src/server_pb.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 85 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 3) integration_tests/feature-store/server/src/model.rs:357— integration_tests/feature-store/server/src/model.rs:357-366 | integration_tests/feature-store/server/src/server_pb.rs:676-685 | integration_tests/feature-store/simulator/src/server_pb.rs:676-685 — before extracting anything, compare `integration_tests/feature-store/server/src/model.rs` and `integration_tests/feature-store/server/src/server_pb.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 85 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8 lines × 3) src/expr/impl/src/scalar/to_char.rs:268— src/expr/impl/src/scalar/to_char.rs:268-275 | src/expr/impl/src/scalar/to_char.rs:286-293 | src/expr/impl/src/scalar/to_char.rs:335-342 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8 lines × 3) src/expr/impl/src/scalar/to_char.rs:267— src/expr/impl/src/scalar/to_char.rs:267-274 | src/expr/impl/src/scalar/to_char.rs:334-341 | src/expr/impl/src/scalar/to_char.rs:344-351 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8 lines × 3) src/frontend/src/optimizer/plan_node/logical_agg.rs:1308— src/frontend/src/optimizer/plan_node/logical_agg.rs:1308-1315 | src/frontend/src/optimizer/plan_node/logical_over_window.rs:575-582 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:281-288 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/logical_agg.rs` and `src/frontend/src/optimizer/plan_node/logical_over_window.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 30 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8 lines × 3) src/frontend/src/optimizer/plan_node/stream_asof_join.rs:227— src/frontend/src/optimizer/plan_node/stream_asof_join.rs:227-234 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:580-587 | src/frontend/src/optimizer/plan_node/stream_temporal_join.rs:245-252 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` and `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8 lines × 3) src/risedevtool/src/bin/risedev-dev.rs:269— src/risedevtool/src/bin/risedev-dev.rs:269-276 | src/risedevtool/src/bin/risedev-dev.rs:351-358 | src/risedevtool/src/bin/risedev-dev.rs:412-420 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8 lines × 3) src/risedevtool/src/task/compactor_service.rs:71— src/risedevtool/src/task/compactor_service.rs:71-78 | src/risedevtool/src/task/compute_node_service.rs:78-85 | src/risedevtool/src/task/meta_node_service.rs:249-256 — before extracting anything, compare `src/risedevtool/src/task/compactor_service.rs` and `src/risedevtool/src/task/compute_node_service.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 30 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8 lines × 3) src/storage/src/mem_table.rs:154— src/storage/src/mem_table.rs:154-161 | src/storage/src/mem_table.rs:212-219 | src/storage/src/mem_table.rs:298-305 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8 lines × 3) src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs:246— src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs:246-253 | src/stream/src/executor/source/fs_list_executor.rs:148-155 | src/stream/src/executor/source/iceberg_list_executor.rs:219-226 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (8 lines × 3) src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs:244— src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs:244-251 | src/frontend/src/optimizer/plan_node/generic/sys_scan.rs:133-140 | src/frontend/src/optimizer/plan_node/generic/table_scan.rs:420-427 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs` and `src/frontend/src/optimizer/plan_node/generic/table_scan.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 41 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8 lines × 3) src/frontend/src/optimizer/plan_node/logical_except.rs:70— src/frontend/src/optimizer/plan_node/logical_except.rs:70-77 | src/frontend/src/optimizer/plan_node/logical_intersect.rs:69-76 | src/frontend/src/optimizer/plan_node/logical_union.rs:91-98 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (8 lines × 3) src/frontend/src/optimizer/plan_node/logical_except.rs:89— src/frontend/src/optimizer/plan_node/logical_except.rs:89-96 | src/frontend/src/optimizer/plan_node/logical_intersect.rs:88-95 | src/frontend/src/optimizer/plan_node/logical_union.rs:110-117 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (8 lines × 3) src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:219— src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:219-226 | src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:200-210 | src/stream/src/executor/source/batch_source/batch_posix_fs_fetch.rs:300-308 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (8 lines × 3) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:99— java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:99-106 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/PostgresDialect.java:132-139 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SqlServerDialect.java:135-142 — before extracting anything, compare `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java` and `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SqlServerDialect.java` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it.
Duplicated block (8 lines × 3) integration_tests/client-library/python/crud.py:12— integration_tests/client-library/python/crud.py:12-25 | integration_tests/client-library/python/crud.py:67-76 | integration_tests/client-library/python/materializeview.py:34-41 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Binder::bind_builtin_scalar_function (cyclomatic 62) src/frontend/src/binder/expr/function/builtin_scalar.rs:31— Binder::bind_builtin_scalar_function has cyclomatic complexity 62 (threshold 15). Of this number, 59 points are the body's own statements and 3 belong to 2 function items inside it that branch. To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
Binder::resolve_binary_operator (cyclomatic 57) src/frontend/src/binder/expr/binary_op.rs:79— Binder::resolve_binary_operator has cyclomatic complexity 57 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Binder::bind_expr_inner (cyclomatic 53) src/frontend/src/binder/expr/mod.rs:66— Binder::bind_expr_inner has cyclomatic complexity 53 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Binder::bind_function (cyclomatic 42) src/frontend/src/binder/expr/function/mod.rs:173— Binder::bind_function has cyclomatic complexity 42 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::bind_match_recognize (cyclomatic 38) src/frontend/src/binder/relation/match_recognize.rs:148— Binder::bind_match_recognize has cyclomatic complexity 38 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::lower_measure (cyclomatic 30) src/frontend/src/binder/relation/match_recognize.rs:540— Binder::lower_measure has cyclomatic complexity 30 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::bind_gap_fill (cyclomatic 25) src/frontend/src/binder/relation/gap_fill.rs:36— Binder::bind_gap_fill has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::bind_catalog_relation_by_name (cyclomatic 25) src/frontend/src/binder/relation/table_or_source.rs:110— Binder::bind_catalog_relation_by_name has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::bind_insert (cyclomatic 22) src/frontend/src/binder/insert.rs:104— Binder::bind_insert has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::bind_update (cyclomatic 19) src/frontend/src/binder/update.rs:125— Binder::bind_update has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::bind_column (cyclomatic 18) src/frontend/src/binder/expr/column.rs:23— Binder::bind_column has cyclomatic complexity 18 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
Binder::bind_window_function (cyclomatic 17) src/frontend/src/binder/expr/function/window.rs:58— Binder::bind_window_function has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Binder::bind_join_constraint (cyclomatic 17) src/frontend/src/binder/relation/join.rs:141— Binder::bind_join_constraint has cyclomatic complexity 17 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
D30 · Dependency Vulnerabilities· Medium advisory (unmaintained) · ×13
HummockManager::get_compact_tasks_impl (cognitive 36) src/meta/src/hummock/manager/compaction/mod.rs:348— HummockManager::get_compact_tasks_impl has cognitive complexity 36 (threshold 15). Drivers by points: if/else 13 (23 pts), loops 5 (8 pts), match/switch 2 (5 pts) (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockManager::truncate_time_travel_metadata (cognitive 36) src/meta/src/hummock/manager/time_travel.rs:70— HummockManager::truncate_time_travel_metadata has cognitive complexity 36 (threshold 15). Drivers by points: if/else 14 (24 pts), loops 9 (12 pts) (nesting depth added 13). Of this number, 35 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockManager::report_compact_tasks_impl (cognitive 34) src/meta/src/hummock/manager/compaction/mod.rs:843— HummockManager::report_compact_tasks_impl has cognitive complexity 34 (threshold 15). Drivers by points: if/else 12 (22 pts), match/switch 3 (7 pts), loops 3, boolean chains 2 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockManager::commit_epoch (cognitive 33) src/meta/src/hummock/manager/commit_epoch.rs:72— HummockManager::commit_epoch has cognitive complexity 33 (threshold 15). Drivers by points: if/else 16 (19 pts), loops 9 (13 pts), boolean chains 1 (nesting depth added 7). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
HummockManager::filter_out_objects_by_time_travel (cognitive 32) src/meta/src/hummock/manager/time_travel.rs:441— HummockManager::filter_out_objects_by_time_travel has cognitive complexity 32 (threshold 15). Drivers by points: if/else 12 (20 pts), loops 6 (12 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockManager::merge_compaction_group_impl (cognitive 29) src/meta/src/hummock/manager/compaction/compaction_group_schedule/topology.rs:66— HummockManager::merge_compaction_group_impl has cognitive complexity 29 (threshold 15). Drivers by points: if/else 19 (23 pts), loops 3, match/switch 1 (2 pts), boolean chains 1 (nesting depth added 5). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
HummockManager::check_dead_task (cognitive 23) src/meta/src/hummock/manager/timer_task.rs:595— HummockManager::check_dead_task has cognitive complexity 23 (threshold 15). Drivers by points: if/else 6 (13 pts), loops 5 (10 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockManager::split_compaction_group_impl (cognitive 22) src/meta/src/hummock/manager/compaction/compaction_group_schedule/topology.rs:456— HummockManager::split_compaction_group_impl has cognitive complexity 22 (threshold 15). Drivers by points: if/else 12 (15 pts), loops 3 (4 pts), boolean chains 3 (nesting depth added 4). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
HummockManager::write_time_travel_metadata (cognitive 22) src/meta/src/hummock/manager/time_travel.rs:646— HummockManager::write_time_travel_metadata has cognitive complexity 22 (threshold 15). Drivers by points: if/else 9 (15 pts), loops 3 (4 pts), boolean chains 3 (nesting depth added 7). Of this number, 14 points are the body's own statements and 8 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockManager::correct_commit_ssts (cognitive 19) src/meta/src/hummock/manager/commit_epoch.rs:387— HummockManager::correct_commit_ssts has cognitive complexity 19 (threshold 15). Drivers by points: if/else 3 (9 pts), loops 5 (7 pts), match/switch 1 (3 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockManager::apply_split_weight_by_vnode_partition (cognitive 18) src/meta/src/hummock/manager/compaction/mod.rs:1231— HummockManager::apply_split_weight_by_vnode_partition has cognitive complexity 18 (threshold 15). Drivers by points: loops 5 (9 pts), if/else 4 (5 pts), boolean chains 4 (nesting depth added 5). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
HummockManager::commit_epoch_sanity_check (cognitive 18) src/meta/src/hummock/manager/context.rs:208— HummockManager::commit_epoch_sanity_check has cognitive complexity 18 (threshold 15). Drivers by points: if/else 9 (14 pts), loops 2, boolean chains 1, match/switch 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
D30 · Dependency Vulnerabilities· Medium advisory (unsound) · ×12
Change-coupling hub: panic_store.rs → replay_impl.rs, hummock_storage.rs, local_hummock_storage.rs, monitored_store.rs, traced_store.rs, store_impl.rs src/storage/src/panic_store.rs— `src/storage/src/panic_store.rs` changes together with 6 other files — `src/storage/hummock_test/src/bin/replay/replay_impl.rs`, `src/storage/src/hummock/store/hummock_storage.rs`, `src/storage/src/hummock/store/local_hummock_storage.rs`, `src/storage/src/monitor/monitored_store.rs`, `src/storage/src/monitor/traced_store.rs`, `src/storage/src/store_impl.rs` — none of which declares a dependency on it: one file is the hub of 6 separate couplings, not 6 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 6.
Change-coupling hub: traced_store.rs → replay_impl.rs, local_hummock_storage.rs, monitored_store.rs src/storage/src/monitor/traced_store.rs— `src/storage/src/monitor/traced_store.rs` changes together with 3 other files — `src/storage/hummock_test/src/bin/replay/replay_impl.rs`, `src/storage/src/hummock/store/local_hummock_storage.rs`, `src/storage/src/monitor/monitored_store.rs` — none of which declares a dependency on it: one file is the hub of 3 separate couplings, not 3 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 3.
Change-coupling hub: store_impl.rs → main.rs, replay_impl.rs, test_utils.rs, test_utils.rs src/storage/src/store_impl.rs— `src/storage/src/store_impl.rs` changes together with 4 other files — `src/storage/hummock_test/src/bin/replay/main.rs`, `src/storage/hummock_test/src/bin/replay/replay_impl.rs`, `src/storage/hummock_test/src/test_utils.rs`, `src/storage/src/hummock/iterator/test_utils.rs` — none of which declares a dependency on it: one file is the hub of 4 separate couplings, not 4 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 4.
Change-coupling hub: batch_hash_join.rs → batch_lookup_join.rs, stream_delta_join.rs, stream_hash_join.rs src/frontend/src/optimizer/plan_node/batch_hash_join.rs— `src/frontend/src/optimizer/plan_node/batch_hash_join.rs` changes together with 3 other files — `src/frontend/src/optimizer/plan_node/batch_lookup_join.rs`, `src/frontend/src/optimizer/plan_node/stream_delta_join.rs`, `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` — none of which declares a dependency on it: one file is the hub of 3 separate couplings, not 3 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 3.
Change-coupling hub: REDACTED → Layout.tsx, streaming.ts, relation_graph.tsx src/meta/src/dashboard/mod.rs— `src/meta/src/dashboard/mod.rs` changes together with 3 other files — `dashboard/components/Layout.tsx`, `dashboard/lib/api/streaming.ts`, `dashboard/pages/relation_graph.tsx` — none of which declares a dependency on it: one file is the hub of 3 separate couplings, not 3 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 3.
Change-coupling hub: kafka.rs → debezium_json.rs, kinesis.rs, nats.rs, pulsar.rs, utils.rs src/connector/src/sink/kafka.rs— `src/connector/src/sink/kafka.rs` changes together with 5 other files — `src/connector/src/sink/formatter/debezium_json.rs`, `src/connector/src/sink/kinesis.rs`, `src/connector/src/sink/nats.rs`, `src/connector/src/sink/pulsar.rs`, `src/connector/src/sink/utils.rs` — none of which declares a dependency on it: one file is the hub of 5 separate couplings, not 5 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 5.
Change-coupling hub: stream_hop_window.rs → stream_dynamic_filter.rs, stream_hash_agg.rs, stream_hash_join.rs, stream_project.rs, stream_project_set.rs, stream_union.rs src/frontend/src/optimizer/plan_node/stream_hop_window.rs— `src/frontend/src/optimizer/plan_node/stream_hop_window.rs` changes together with 6 other files — `src/frontend/src/optimizer/plan_node/stream_dynamic_filter.rs`, `src/frontend/src/optimizer/plan_node/stream_hash_agg.rs`, `src/frontend/src/optimizer/plan_node/stream_hash_join.rs`, `src/frontend/src/optimizer/plan_node/stream_project.rs`, `src/frontend/src/optimizer/plan_node/stream_project_set.rs`, `src/frontend/src/optimizer/plan_node/stream_union.rs` — none of which declares a dependency on it: one file is the hub of 6 separate couplings, not 6 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 6.
Change-coupling hub: reader.rs → reader.rs, reader.rs, reader.rs src/connector/src/source/nexmark/source/reader.rs— `src/connector/src/source/nexmark/source/reader.rs` changes together with 3 other files — `src/connector/src/source/cdc/source/reader.rs`, `src/connector/src/source/datagen/source/reader.rs`, `src/connector/src/source/kafka/source/reader.rs` — none of which declares a dependency on it: one file is the hub of 3 separate couplings, not 3 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 3.
Change-coupling hub: stream_union.rs → stream_dynamic_filter.rs, stream_hash_agg.rs, stream_project.rs, stream_stateless_simple_agg.rs src/frontend/src/optimizer/plan_node/stream_union.rs— `src/frontend/src/optimizer/plan_node/stream_union.rs` changes together with 4 other files — `src/frontend/src/optimizer/plan_node/stream_dynamic_filter.rs`, `src/frontend/src/optimizer/plan_node/stream_hash_agg.rs`, `src/frontend/src/optimizer/plan_node/stream_project.rs`, `src/frontend/src/optimizer/plan_node/stream_stateless_simple_agg.rs` — none of which declares a dependency on it: one file is the hub of 4 separate couplings, not 4 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 4.
Change-coupling hub: REDACTED → config.rs, risedev_env.rs, service_config.rs src/risedevtool/src/task/mod.rs— `src/risedevtool/src/task/mod.rs` changes together with 3 other files — `src/risedevtool/src/config.rs`, `src/risedevtool/src/risedev_env.rs`, `src/risedevtool/src/service_config.rs` — none of which declares a dependency on it: one file is the hub of 3 separate couplings, not 3 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 3.
Change-coupling hub: scale_service.rs → recovery.rs, scale.rs, stream_manager.rs src/meta/service/src/scale_service.rs— `src/meta/service/src/scale_service.rs` changes together with 3 other files — `src/meta/src/barrier/context/recovery.rs`, `src/meta/src/stream/scale.rs`, `src/meta/src/stream/stream_manager.rs` — none of which declares a dependency on it: one file is the hub of 3 separate couplings, not 3 unrelated pairs. Read the hub first: if the others each duplicate a part of what it does, the shared concern belongs in ONE unit and extracting it clears every edge at once; if the hub is a registry, dispatcher or barrel that must name each of them, the coupling is structural and the question is whether that list can be discovered instead of enumerated. Fixing the hub is one change; breaking the couplings one pair at a time is 3.
Duplicated block (19 lines × 2) src/connector/src/sink/coordinate.rs:134— src/connector/src/sink/coordinate.rs:134-152 | src/connector/src/sink/decouple_checkpoint_log_sink.rs:76-94 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (19 lines × 2) src/connector/src/sink/doris_starrocks_connector.rs:306— src/connector/src/sink/doris_starrocks_connector.rs:306-324 | src/connector/src/sink/doris_starrocks_connector.rs:636-654 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (19 lines × 2) src/frontend/src/optimizer/plan_node/batch_over_window.rs:102— src/frontend/src/optimizer/plan_node/batch_over_window.rs:102-120 | src/frontend/src/optimizer/plan_node/stream_over_window.rs:162-180 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (19 lines × 2) src/frontend/src/scheduler/local.rs:543— src/frontend/src/scheduler/local.rs:543-561 | src/frontend/src/scheduler/local.rs:566-584 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (19 lines × 2) src/meta/src/hummock/compaction/picker/space_reclaim_compaction_picker.rs:83— src/meta/src/hummock/compaction/picker/space_reclaim_compaction_picker.rs:83-101 | src/meta/src/hummock/compaction/picker/space_reclaim_compaction_picker.rs:137-157 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (19 lines × 2) src/meta/src/rpc/ddl_controller.rs:1373— src/meta/src/rpc/ddl_controller.rs:1373-1391 | src/meta/src/rpc/ddl_controller.rs:1432-1450 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (19 lines × 2) src/storage/src/hummock/store/local_hummock_storage.rs:441— src/storage/src/hummock/store/local_hummock_storage.rs:441-459 | src/storage/src/memory.rs:1120-1138 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (19 lines × 2) src/stream/src/executor/nested_loop_temporal_join.rs:194— src/stream/src/executor/nested_loop_temporal_join.rs:194-212 | src/stream/src/executor/temporal_join.rs:736-754 — before extracting anything, compare `src/stream/src/executor/nested_loop_temporal_join.rs` and `src/stream/src/executor/temporal_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 102 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (19 lines × 2) src/stream/src/executor/top_n/top_n_cache.rs:419— src/stream/src/executor/top_n/top_n_cache.rs:419-437 | src/stream/src/executor/top_n/top_n_cache.rs:459-477 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (19 lines × 2) src/stream/src/from_proto/eowc_gap_fill.rs:52— src/stream/src/from_proto/eowc_gap_fill.rs:52-70 | src/stream/src/from_proto/gap_fill.rs:50-68 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (19 lines × 2) docs/metrics/extract.py:556— docs/metrics/extract.py:556-574 | docs/metrics/extract.py:591-609 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it.
risingwave_ctl::cmd_impl::meta::cluster_info::source_split_info (cognitive 38) src/ctl/src/cmd_impl/meta/cluster_info.rs:35— risingwave_ctl::cmd_impl::meta::cluster_info::source_split_info has cognitive complexity 38 (threshold 15). Drivers by points: if/else 9 (24 pts), loops 6 (12 pts), boolean chains 2 (nesting depth added 21). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_ctl::cmd_impl::hummock::compaction_group::build_compaction_config_vec (cognitive 30) src/ctl/src/cmd_impl/hummock/compaction_group.rs:53— risingwave_ctl::cmd_impl::hummock::compaction_group::build_compaction_config_vec has cognitive complexity 30 (threshold 15). Drivers by points: if/else 30. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
risingwave_ctl::cmd_impl::hummock::sst_dump::sst_dump (cognitive 30) src/ctl/src/cmd_impl/hummock/sst_dump.rs:70— risingwave_ctl::cmd_impl::hummock::sst_dump::sst_dump has cognitive complexity 30 (threshold 15). Drivers by points: if/else 9 (17 pts), loops 3 (8 pts), match/switch 1 (4 pts), boolean chains 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_ctl::cmd_impl::meta::reschedule::unregister_workers (cognitive 30) src/ctl/src/cmd_impl/meta/reschedule.rs:183— risingwave_ctl::cmd_impl::meta::reschedule::unregister_workers has cognitive complexity 30 (threshold 15). Drivers by points: if/else 9 (18 pts), loops 4 (5 pts), match/switch 3 (5 pts), boolean chains 2 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_ctl::cmd_impl::hummock::list_version::list_version (cognitive 22) src/ctl/src/cmd_impl/hummock/list_version.rs:20— risingwave_ctl::cmd_impl::hummock::list_version::list_version has cognitive complexity 22 (threshold 15). Drivers by points: loops 7 (18 pts), if/else 3, boolean chains 1 (nesting depth added 11). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_ctl::cmd_impl::hummock::validate_version::print_version_delta_in_archive (cognitive 21) src/ctl/src/cmd_impl/hummock/validate_version.rs:171— risingwave_ctl::cmd_impl::hummock::validate_version::print_version_delta_in_archive has cognitive complexity 21 (threshold 15). Drivers by points: if/else 2 (11 pts), loops 4 (10 pts) (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_ctl::cmd_impl::meta::cluster_info::cluster_info (cognitive 18) src/ctl/src/cmd_impl/meta/cluster_info.rs:138— risingwave_ctl::cmd_impl::meta::cluster_info::cluster_info has cognitive complexity 18 (threshold 15). Drivers by points: loops 6 (10 pts), if/else 4 (7 pts), match/switch 1 (nesting depth added 7). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_ctl::cmd_impl::hummock::compaction_group::list_compaction_status (cognitive 17) src/ctl/src/cmd_impl/hummock/compaction_group.rs:197— risingwave_ctl::cmd_impl::hummock::compaction_group::list_compaction_status has cognitive complexity 17 (threshold 15). Drivers by points: loops 6 (15 pts), if/else 2 (nesting depth added 9). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_ctl::cmd_impl::bench::do_bench (cognitive 17) src/ctl/src/cmd_impl/bench.rs:82— risingwave_ctl::cmd_impl::bench::do_bench has cognitive complexity 17 (threshold 15). Drivers by points: loops 5 (13 pts), if/else 1 (3 pts), match/switch 1 (nesting depth added 10). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_ctl::cmd_impl::hummock::migrate_legacy_object::migrate_legacy_object (cognitive 17) src/ctl/src/cmd_impl/hummock/migrate_legacy_object.rs:30— risingwave_ctl::cmd_impl::hummock::migrate_legacy_object::migrate_legacy_object has cognitive complexity 17 (threshold 15). Drivers by points: if/else 9 (15 pts), boolean chains 1, loops 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (22 lines × 2) src/connector/src/sink/iceberg/commit.rs:369— src/connector/src/sink/iceberg/commit.rs:369-390 | src/connector/src/sink/iceberg/commit.rs:550-571 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (22 lines × 2) src/frontend/planner_test/src/lib.rs:448— src/frontend/planner_test/src/lib.rs:448-469 | src/frontend/src/handler/mod.rs:468-489 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (22 lines × 2) src/frontend/src/handler/describe.rs:366— src/frontend/src/handler/describe.rs:366-387 | src/frontend/src/utils/stream_graph_formatter.rs:238-259 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (22 lines × 2) src/meta/service/src/ddl_service.rs:1183— src/meta/service/src/ddl_service.rs:1183-1204 | src/meta/service/src/ddl_service.rs:1239-1260 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (22 lines × 2) src/meta/src/hummock/model/ext/hummock.rs:315— src/meta/src/hummock/model/ext/hummock.rs:315-336 | src/storage/backup/src/meta_snapshot_v2.rs:257-278 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (22 lines × 2) src/sqlparser/src/parser.rs:5889— src/sqlparser/src/parser.rs:5889-5910 | src/sqlparser/src/parser.rs:6600-6621 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (22 lines × 2) src/stream/src/executor/source/fs_fetch_executor.rs:464— src/stream/src/executor/source/fs_fetch_executor.rs:464-485 | src/stream/src/executor/source/iceberg_fetch_executor.rs:410-431 — before extracting anything, compare `src/stream/src/executor/source/fs_fetch_executor.rs` and `src/stream/src/executor/source/iceberg_fetch_executor.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 71 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (22 lines × 2) src/stream/src/executor/top_n/group_top_n.rs:116— src/stream/src/executor/top_n/group_top_n.rs:116-137 | src/stream/src/executor/top_n/group_top_n_appendonly.rs:122-143 — before extracting anything, compare `src/stream/src/executor/top_n/group_top_n.rs` and `src/stream/src/executor/top_n/group_top_n_appendonly.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 69 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (22 lines × 2) java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:389— java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:389-410 | java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:578-599 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:389` it runs out through the closing brace of the declaration holding it — the window is that declaration's tail, not a fragment that begins part-way through something, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just after the matched lines, `java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:412` calls `probeConnectionIfNeeded` and `java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:601` does not — after which the two agree again for 2 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
Duplicated block (22 lines × 2) REDACTED:124— REDACTED:124-145 | REDACTED:149-170 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Outbound HTTP without resilience dashboard/lib/api/api.ts:48— `fetch(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout. 14 of the 19 files that make outbound calls are unbounded; the first 10 are listed.
Outbound HTTP without resilience java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/ElasticRestHighLevelClientAdapter.java:61— `RestClient.builder(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/OpensearchRestHighLevelClientAdapter.java:58— `RestClient.builder(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience src/common/secret/src/vault_client.rs:170— `Client::builder()` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience src/common/src/telemetry/mod.rs:180— `reqwest::get(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience src/common/telemetry_event/src/util.rs:32— `reqwest::Client::new(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience src/connector/codec/src/decoder/json/mod.rs:133— `reqwest::get(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience src/connector/src/parser/utils.rs:70— `reqwest::get(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience src/connector/src/sink/doris.rs:493— `reqwest::Client::builder(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
Outbound HTTP without resilience src/connector/src/sink/http.rs:310— `reqwest::Client::builder(` makes an outbound HTTP call, and nothing bounds it: no timeout, deadline, retry or circuit breaker is set for it here, and the client has no process-wide default. A slow or failing dependency will hold this service's request, thread or connection until the call gives up on its own — or never, for a client with no default timeout.
risingwave_storage::hummock::compactor::start_iceberg_compactor (cyclomatic 38) src/storage/src/hummock/compactor/mod.rs:400— risingwave_storage::hummock::compactor::start_iceberg_compactor has cyclomatic complexity 38 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_storage::hummock::compactor::start_compactor (cyclomatic 30) src/storage/src/hummock/compactor/mod.rs:951— risingwave_storage::hummock::compactor::start_compactor has cyclomatic complexity 30 (threshold 15). Of this number, 29 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_storage::hummock::compactor::iceberg_compaction::memory::estimate_plan_memory (cyclomatic 27) src/storage/src/hummock/compactor/iceberg_compaction/memory.rs:59— risingwave_storage::hummock::compactor::iceberg_compaction::memory::estimate_plan_memory has cyclomatic complexity 27 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
risingwave_storage::hummock::compactor::compactor_runner::compact_and_build_sst (cyclomatic 23) src/storage/src/hummock/compactor/compactor_runner.rs:758— risingwave_storage::hummock::compactor::compactor_runner::compact_and_build_sst has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_storage::hummock::compactor::start_shared_compactor (cyclomatic 19) src/storage/src/hummock/compactor/mod.rs:1320— risingwave_storage::hummock::compactor::start_shared_compactor has cyclomatic complexity 19 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_storage::hummock::compactor::compactor_runner::compact_with_agent (cyclomatic 18) src/storage/src/hummock/compactor/compactor_runner.rs:323— risingwave_storage::hummock::compactor::compactor_runner::compact_with_agent has cyclomatic complexity 18 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_storage::hummock::compactor::iceberg_compaction::iceberg_compactor_runner::build_task_planning_config (cyclomatic 18) src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:756— risingwave_storage::hummock::compactor::iceberg_compaction::iceberg_compactor_runner::build_task_planning_config has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_storage::hummock::compactor::shared_buffer_compact::compact_shared_buffer (cyclomatic 18) src/storage/src/hummock/compactor/shared_buffer_compact.rs:145— risingwave_storage::hummock::compactor::shared_buffer_compact::compact_shared_buffer has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_storage::hummock::local_version::pinned_version::start_pinned_version_worker (cyclomatic 16) src/storage/src/hummock/local_version/pinned_version.rs:197— risingwave_storage::hummock::local_version::pinned_version::start_pinned_version_worker has cyclomatic complexity 16 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
CatalogController::drop_object (cyclomatic 36) src/meta/src/controller/catalog/drop_op.rs:24— CatalogController::drop_object has cyclomatic complexity 36 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CatalogController::create_job_catalog (cyclomatic 25) src/meta/src/controller/streaming_job.rs:467— CatalogController::create_job_catalog has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CatalogController::finish_replace_streaming_job_inner (cyclomatic 23) src/meta/src/controller/streaming_job.rs:2034— CatalogController::finish_replace_streaming_job_inner has cyclomatic complexity 23 (threshold 15). Of this number, 18 points are the body's own statements and 5 belong to one function item inside it that branches. To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
CatalogController::update_connection_and_dependent_objects_props (cyclomatic 23) src/meta/src/controller/streaming_job.rs:3280— CatalogController::update_connection_and_dependent_objects_props has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CatalogController::alter_owner (cyclomatic 21) src/meta/src/controller/catalog/alter_op.rs:281— CatalogController::alter_owner has cyclomatic complexity 21 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
CatalogController::update_fragment_rate_limit_by_fragment_id (cyclomatic 20) src/meta/src/controller/streaming_job.rs:3747— CatalogController::update_fragment_rate_limit_by_fragment_id has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CatalogController::try_abort_creating_streaming_job (cyclomatic 19) src/meta/src/controller/streaming_job.rs:1022— CatalogController::try_abort_creating_streaming_job has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CatalogController::revoke_privilege (cyclomatic 16) src/meta/src/controller/user.rs:340— CatalogController::revoke_privilege has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CatalogController::grant_default_privileges (cyclomatic 16) src/meta/src/controller/user.rs:520— CatalogController::grant_default_privileges has cyclomatic complexity 16 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
Duplicated block (5 lines × 3) src/frontend/src/optimizer/plan_node/batch_delete.rs:62— src/frontend/src/optimizer/plan_node/batch_delete.rs:62-66 | src/frontend/src/optimizer/plan_node/batch_insert.rs:74-78 | src/frontend/src/optimizer/plan_node/batch_update.rs:65-69 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (5 lines × 3) src/frontend/src/optimizer/plan_node/stream_hash_agg.rs:200— src/frontend/src/optimizer/plan_node/stream_hash_agg.rs:200-204 | src/frontend/src/optimizer/plan_node/stream_simple_agg.rs:122-126 | src/frontend/src/optimizer/plan_node/stream_stateless_simple_agg.rs:96-100 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (5 lines × 3) src/risedevtool/src/bin/risedev-dev.rs:176— src/risedevtool/src/bin/risedev-dev.rs:176-180 | src/risedevtool/src/bin/risedev-dev.rs:224-228 | src/risedevtool/src/bin/risedev-dev.rs:429-434 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 3) src/stream/src/executor/top_n/top_n_state.rs:179— src/stream/src/executor/top_n/top_n_state.rs:179-184 | src/stream/src/executor/top_n/top_n_state.rs:251-255 | src/stream/src/executor/top_n/top_n_state.rs:283-287 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 3) src/frontend/src/optimizer/plan_node/logical_table_function.rs:81— src/frontend/src/optimizer/plan_node/logical_table_function.rs:81-85 | src/frontend/src/optimizer/plan_node/logical_values.rs:99-103 | src/frontend/src/optimizer/plan_node/logical_vector_search.rs:241-245 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (5 lines × 3) src/frontend/src/optimizer/plan_node/stream_delta_join.rs:237— src/frontend/src/optimizer/plan_node/stream_delta_join.rs:237-241 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:730-734 | src/frontend/src/optimizer/plan_node/stream_stateless_simple_agg.rs:119-123 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (5 lines × 3) src/frontend/src/optimizer/plan_node/stream_over_window.rs:150— src/frontend/src/optimizer/plan_node/stream_over_window.rs:150-154 | src/frontend/src/optimizer/plan_node/stream_stateless_simple_agg.rs:81-85 | src/frontend/src/optimizer/plan_node/stream_topn.rs:97-101 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (5 lines × 3) src/cmd_all/src/standalone.rs:110— src/cmd_all/src/standalone.rs:110-114 | src/cmd_all/src/standalone.rs:117-121 | src/cmd_all/src/standalone.rs:124-128 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 3) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/FileSinkFactory.java:30— java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/FileSinkFactory.java:30-34 | java/connector-node/risingwave-sink-cassandra/src/main/java/com/risingwave/connector/CassandraFactory.java:39-43 | java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/EsSinkFactory.java:36-40 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it.
Off the main sequence: delta_btree_map — delta_btree_map: abstractness 0.00, instability 0.00, distance 1.00 — zone of pain — concrete and depended on by 1 project(s), so it's rigid to change.
Off the main sequence: risingwave_common_log — risingwave_common_log: abstractness 0.00, instability 0.00, distance 1.00 — the shape a shared-kernel / building-block library has BY DESIGN — concrete and widely depended-on is what makes it useful, and this dimension does not penalise it (the distance is reported for completeness, not as a defect). Worth a look only if it has grown past one coherent kernel into an everything-bucket.
Off the main sequence: risingwave_error — risingwave_error: abstractness 0.00, instability 0.00, distance 1.00 — zone of pain — concrete and depended on by 3 project(s), so it's rigid to change.
Off the main sequence: risingwave_meta_dashboard — risingwave_meta_dashboard: abstractness 0.00, instability 0.00, distance 1.00 — zone of pain — concrete and depended on by 1 project(s), so it's rigid to change.
Off the main sequence: sync-point — sync-point: abstractness 0.00, instability 0.00, distance 1.00 — zone of pain — concrete and depended on by 2 project(s), so it's rigid to change.
Off the main sequence: risingwave_sqlparser — risingwave_sqlparser: abstractness 0.05, instability 0.14, distance 0.81 — zone of pain — concrete and depended on by 6 project(s), so it's rigid to change.
Off the main sequence: risingwave_object_store — risingwave_object_store: abstractness 0.07, instability 0.13, distance 0.80 — zone of pain — concrete and depended on by 7 project(s), so it's rigid to change.
Off the main sequence: common-utils — common-utils: abstractness 0.00, instability 0.25, distance 0.75 — the shape a shared-kernel / building-block library has BY DESIGN — concrete and widely depended-on is what makes it useful, and this dimension does not penalise it (the distance is reported for completeness, not as a defect). Worth a look only if it has grown past one coherent kernel into an everything-bucket.
Off the main sequence: risingwave_dml — risingwave_dml: abstractness 0.00, instability 0.29, distance 0.71 — zone of pain — concrete and depended on by 5 project(s), so it's rigid to change.
risingwave_common::system_param::set_system_param (cognitive 145) src/common/src/system_param/mod.rs:329— risingwave_common::system_param::set_system_param has cognitive complexity 145 (threshold 15). Drivers by points: if/else 90 (144 pts), match/switch 1 (nesting depth added 54). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_common::types::variant::parse_path (cognitive 53) src/common/src/types/variant.rs:907— risingwave_common::types::variant::parse_path has cognitive complexity 53 (threshold 15). Drivers by points: if/else 9 (33 pts), loops 5 (15 pts), boolean chains 3, match/switch 1 (2 pts) (nesting depth added 35). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_common::vnode_mapping::vnode_placement::place_vnode (cognitive 39) src/common/src/vnode_mapping/vnode_placement.rs:29— risingwave_common::vnode_mapping::vnode_placement::place_vnode has cognitive complexity 39 (threshold 15). Drivers by points: if/else 15 (28 pts), loops 7 (10 pts), match/switch 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_common::system_param::derive_missing_fields (cognitive 36) src/common/src/system_param/mod.rs:208— risingwave_common::system_param::derive_missing_fields has cognitive complexity 36 (threshold 15). Drivers by points: boolean chains 18, if/else 18. To reduce it, name the conditions: bind each compound test to a well-named local or a small predicate function, so the body reads as a sequence of named decisions rather than a chain of operators.
risingwave_common::util::stream_graph_visitor::visit_stream_node_tables_inner (cognitive 35) src/common/src/util/stream_graph_visitor.rs:104— risingwave_common::util::stream_graph_visitor::visit_stream_node_tables_inner has cognitive complexity 35 (threshold 15). Drivers by points: if/else 12 (19 pts), loops 6 (11 pts), match/switch 3 (5 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_common::array::arrow::arrow_impl::is_parquet_schema_match_source_schema (cognitive 25) src/common/src/array/arrow/arrow_impl.rs:1841— risingwave_common::array::arrow::arrow_impl::is_parquet_schema_match_source_schema has cognitive complexity 25 (threshold 15). Drivers by points: if/else 8 (20 pts), boolean chains 2, loops 1 (2 pts), match/switch 1 (nesting depth added 13). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_common::system_param::check_missing_params (cognitive 18) src/common/src/system_param/mod.rs:175— risingwave_common::system_param::check_missing_params has cognitive complexity 18 (threshold 15). Drivers by points: if/else 18. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_common::system_param::validate_init_system_params) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
risingwave_common::system_param::validate_init_system_params (cognitive 18) src/common/src/system_param/mod.rs:420— risingwave_common::system_param::validate_init_system_params has cognitive complexity 18 (threshold 15). Drivers by points: if/else 18. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_common::system_param::check_missing_params) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
risingwave_expr_impl::scalar::to_char::format_inner (cognitive 63) src/expr/impl/src/scalar/to_char.rs:244— risingwave_expr_impl::scalar::to_char::format_inner has cognitive complexity 63 (threshold 15). Drivers by points: if/else 28 (58 pts), match/switch 3 (5 pts) (nesting depth added 32). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_expr_impl::scalar::regexp::regexp_replace (cognitive 60) src/expr/impl/src/scalar/regexp.rs:271— risingwave_expr_impl::scalar::regexp::regexp_replace has cognitive complexity 60 (threshold 15). Drivers by points: if/else 18 (45 pts), loops 3 (11 pts), boolean chains 2, match/switch 2 (nesting depth added 35). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
risingwave_expr_impl::scalar::jsonb_set::jsonbb_set_path (cognitive 38) src/expr/impl/src/scalar/jsonb_set.rs:75— risingwave_expr_impl::scalar::jsonb_set::jsonbb_set_path has cognitive complexity 38 (threshold 15). Drivers by points: if/else 12 (28 pts), loops 3 (8 pts), boolean chains 1, match/switch 1 (nesting depth added 21). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_expr_impl::scalar::jsonb_delete::jsonbb_remove_path (cognitive 25) src/expr/impl/src/scalar/jsonb_delete.rs:307— risingwave_expr_impl::scalar::jsonb_delete::jsonbb_remove_path has cognitive complexity 25 (threshold 15). Drivers by points: if/else 8 (20 pts), loops 2 (4 pts), match/switch 1 (nesting depth added 14). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_expr_impl::scalar::regexp::regexp_split_to_array (cognitive 20) src/expr/impl/src/scalar/regexp.rs:466— risingwave_expr_impl::scalar::regexp::regexp_split_to_array has cognitive complexity 20 (threshold 15). Drivers by points: if/else 9 (18 pts), boolean chains 1, loops 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_expr_impl::scalar::array_concat::array_cat (cognitive 19) src/expr/impl/src/scalar/array_concat.rs:91— risingwave_expr_impl::scalar::array_concat::array_cat has cognitive complexity 19 (threshold 15). Drivers by points: if/else 13 (16 pts), boolean chains 3 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
risingwave_expr_impl::scalar::similar_to_escape::similar_escape_internal (cognitive 18) src/expr/impl/src/scalar/similar_to_escape.rs:20— risingwave_expr_impl::scalar::similar_to_escape::similar_escape_internal has cognitive complexity 18 (threshold 15). Drivers by points: if/else 4 (10 pts), match/switch 2 (6 pts), boolean chains 1, loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_expr_impl::window_function::range_utils::range_diff (cognitive 17) src/expr/impl/src/window_function/range_utils.rs:57— risingwave_expr_impl::window_function::range_utils::range_diff has cognitive complexity 17 (threshold 15). Drivers by points: if/else 10 (12 pts), boolean chains 3, match/switch 1 (2 pts) (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
D30 · Dependency Vulnerabilities· Medium vulnerability · ×8
Duplicated block (9–10 lines × 2) src/connector/src/connector_common/iceberg/mod.rs:686— src/connector/src/connector_common/iceberg/mod.rs:686-694 | src/connector/src/connector_common/iceberg/mod.rs:1075-1084 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9–10 lines × 2) src/connector/src/source/cdc/enumerator/mod.rs:330— src/connector/src/source/cdc/enumerator/mod.rs:330-338 | REDACTED:248-257 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (9–10 lines × 2) src/expr/impl/src/scalar/encdec.rs:132— src/expr/impl/src/scalar/encdec.rs:132-141 | src/expr/impl/src/scalar/encdec.rs:156-164 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9–10 lines × 2) src/frontend/src/optimizer/plan_node/logical_join.rs:301— src/frontend/src/optimizer/plan_node/logical_join.rs:301-309 | src/frontend/src/optimizer/plan_node/logical_join.rs:1161-1170 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9–10 lines × 2) src/frontend/src/optimizer/plan_node/logical_union.rs:218— src/frontend/src/optimizer/plan_node/logical_union.rs:218-226 | src/frontend/src/optimizer/plan_node/logical_union.rs:308-317 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9–10 lines × 2) src/meta/src/controller/fragment.rs:1355— src/meta/src/controller/fragment.rs:1355-1364 | src/meta/src/stream/scale.rs:632-640 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (9–10 lines × 2) src/meta/src/controller/catalog/alter_op.rs:488— src/meta/src/controller/catalog/alter_op.rs:488-497 | src/meta/src/controller/catalog/util.rs:328-336 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (9–10 lines × 2) src/stream/src/executor/top_n/group_top_n.rs:237— src/stream/src/executor/top_n/group_top_n.rs:237-245 | src/stream/src/executor/top_n/group_top_n_appendonly.rs:206-215 — before extracting anything, compare `src/stream/src/executor/top_n/group_top_n.rs` and `src/stream/src/executor/top_n/group_top_n_appendonly.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 69 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (9 lines × 3) src/batch/executors/src/executor/hash_agg.rs:399— src/batch/executors/src/executor/hash_agg.rs:399-407 | src/batch/executors/src/executor/join/hash_join.rs:342-350 | src/batch/executors/src/executor/join/hash_join.rs:370-378 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/join/hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 81 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (9 lines × 3) src/connector/src/sink/doris.rs:397— src/connector/src/sink/doris.rs:397-405 | src/connector/src/sink/doris.rs:410-418 | src/connector/src/sink/doris.rs:424-432 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (9 lines × 3) src/frontend/src/optimizer/plan_node/generic/join.rs:246— src/frontend/src/optimizer/plan_node/generic/join.rs:246-254 | src/frontend/src/optimizer/plan_node/stream_asof_join.rs:182-190 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:375-383 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/join.rs` and `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 31 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (9 lines × 3) src/frontend/src/scheduler/distributed/stage.rs:748— src/frontend/src/scheduler/distributed/stage.rs:748-756 | src/frontend/src/scheduler/fast_insert.rs:44-52 | src/frontend/src/scheduler/local.rs:655-663 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (9 lines × 3) src/frontend/src/handler/alter_connection_props.rs:49— src/frontend/src/handler/alter_connection_props.rs:49-57 | src/frontend/src/handler/alter_sink_props.rs:59-67 | src/frontend/src/handler/alter_table_props.rs:87-95 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (9 lines × 3) src/storage/src/mem_table.rs:163— src/storage/src/mem_table.rs:163-171 | src/storage/src/mem_table.rs:221-229 | src/storage/src/mem_table.rs:307-315 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (9 lines × 3) src/frontend/src/binder/select.rs:74— src/frontend/src/binder/select.rs:74-82 | src/frontend/src/binder/select.rs:84-92 | src/frontend/src/binder/select.rs:93-102 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (9 lines × 3) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:313— java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:313-321 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:312-320 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java:279-287 — before extracting anything, compare `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java` and `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 34 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:313` it does not close everything it opens, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
risingwave_common::system_param::set_system_param (cyclomatic 73) src/common/src/system_param/mod.rs:329— risingwave_common::system_param::set_system_param has cyclomatic complexity 73 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_common::util::stream_graph_visitor::visit_stream_node_tables_inner (cyclomatic 53) src/common/src/util/stream_graph_visitor.rs:104— risingwave_common::util::stream_graph_visitor::visit_stream_node_tables_inner has cyclomatic complexity 53 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_common::system_param::derive_missing_fields (cyclomatic 37) src/common/src/system_param/mod.rs:208— risingwave_common::system_param::derive_missing_fields has cyclomatic complexity 37 (threshold 15). To reduce it, name the conditions: bind each compound test to a well-named local or a small predicate function, so the body reads as a sequence of named decisions rather than a chain of operators.
risingwave_common::vnode_mapping::vnode_placement::place_vnode (cyclomatic 22) src/common/src/vnode_mapping/vnode_placement.rs:29— risingwave_common::vnode_mapping::vnode_placement::place_vnode has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_common::types::variant::parse_path (cyclomatic 20) src/common/src/types/variant.rs:907— risingwave_common::types::variant::parse_path has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: risingwave_common::types::variant::append_datum_value (cyclomatic 26) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
risingwave_common::system_param::check_missing_params (cyclomatic 19) src/common/src/system_param/mod.rs:175— risingwave_common::system_param::check_missing_params has cyclomatic complexity 19 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_common::system_param::validate_init_system_params) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared. This is NOT this file's highest cyclomatic complexity: risingwave_common::system_param::system_params_from_kv (cyclomatic 20) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
risingwave_common::system_param::validate_init_system_params (cyclomatic 19) src/common/src/system_param/mod.rs:420— risingwave_common::system_param::validate_init_system_params has cyclomatic complexity 19 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_common::system_param::check_missing_params) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared. This is NOT this file's highest cyclomatic complexity: risingwave_common::system_param::system_params_from_kv (cyclomatic 20) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
risingwave_meta::controller::system_param::merge_params (cyclomatic 55) src/meta/src/controller/system_param.rs:112— risingwave_meta::controller::system_param::merge_params has cyclomatic complexity 55 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_meta::hummock::manager::compaction::compaction_group_manager::update_compaction_config (cyclomatic 39) src/meta/src/hummock/manager/compaction/compaction_group_manager.rs:660— risingwave_meta::hummock::manager::compaction::compaction_group_manager::update_compaction_config has cyclomatic complexity 39 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_meta::controller::utils::check_relation_name_duplicate (cyclomatic 26) src/meta/src/controller/utils.rs:803— risingwave_meta::controller::utils::check_relation_name_duplicate has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_meta::dashboard::handlers::get_streaming_stats_from_prometheus (cyclomatic 24) src/meta/src/dashboard/mod.rs:778— risingwave_meta::dashboard::handlers::get_streaming_stats_from_prometheus has cyclomatic complexity 24 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_meta::stream::stream_graph::state_match::match_graph (cyclomatic 18) src/meta/src/stream/stream_graph/state_match.rs:420— risingwave_meta::stream::stream_graph::state_match::match_graph has cyclomatic complexity 18 (threshold 15). Most of this is not in the body itself: 5 of the 18 points are its own statements and the rest belongs to one function item inside it that branches (dfs). Those helpers are already separate functions, so extracting the branching again is not available. To reduce it, move them out of the body to the enclosing scope, where each is measured, reviewed and tested on its own, and reduce whichever one then reads as the largest.
risingwave_meta::hummock::metrics_utils::trigger_sst_stat (cyclomatic 16) src/meta/src/hummock/metrics_utils.rs:138— risingwave_meta::hummock::metrics_utils::trigger_sst_stat has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_meta::serving::start_serving_vnode_mapping_worker (cyclomatic 16) src/meta/src/serving/mod.rs:267— risingwave_meta::serving::start_serving_vnode_mapping_worker has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HummockManager::truncate_time_travel_metadata (cyclomatic 24) src/meta/src/hummock/manager/time_travel.rs:70— HummockManager::truncate_time_travel_metadata has cyclomatic complexity 24 (threshold 15). Of this number, 23 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HummockManager::commit_epoch (cyclomatic 23) src/meta/src/hummock/manager/commit_epoch.rs:72— HummockManager::commit_epoch has cyclomatic complexity 23 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
HummockManager::merge_compaction_group_impl (cyclomatic 22) src/meta/src/hummock/manager/compaction/compaction_group_schedule/topology.rs:66— HummockManager::merge_compaction_group_impl has cyclomatic complexity 22 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
HummockManager::get_compact_tasks_impl (cyclomatic 19) src/meta/src/hummock/manager/compaction/mod.rs:348— HummockManager::get_compact_tasks_impl has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HummockManager::report_compact_tasks_impl (cyclomatic 19) src/meta/src/hummock/manager/compaction/mod.rs:843— HummockManager::report_compact_tasks_impl has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HummockManager::split_compaction_group_impl (cyclomatic 18) src/meta/src/hummock/manager/compaction/compaction_group_schedule/topology.rs:456— HummockManager::split_compaction_group_impl has cyclomatic complexity 18 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
HummockManager::write_time_travel_metadata (cyclomatic 16) src/meta/src/hummock/manager/time_travel.rs:646— HummockManager::write_time_travel_metadata has cyclomatic complexity 16 (threshold 15). Of this number, 12 points are the body's own statements and 4 belong to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
TooManyFunctions: risingwave_common::config::default::developer src/common/src/config/mod.rs:172— TooManyFunctions — 80 free functions. The bar is 30 free functions; this is 50 over it, 2.67× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyFunctions: risingwave_common::config::meta::default::meta src/common/src/config/meta.rs:704— TooManyFunctions — 59 free functions. The bar is 30 free functions; this is 29 over it, 1.97× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyFunctions: risingwave_expr_impl::scalar::arithmetic_op src/expr/impl/src/scalar/arithmetic_op.rs:30— TooManyFunctions — 48 free functions. The bar is 30 free functions; this is 18 over it, 1.60× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyFunctions: risingwave_common::util::value_encoding src/common/src/util/value_encoding/mod.rs:131— TooManyFunctions — 40 free functions. The bar is 30 free functions; this is 10 over it, 1.33× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyFunctions: risingwave_expr_impl::scalar::trigonometric src/expr/impl/src/scalar/trigonometric.rs:19— TooManyFunctions — 37 free functions. The bar is 30 free functions; this is 7 over it, 1.23× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyFunctions: risingwave_common::config::meta::default::compaction_config src/common/src/config/meta.rs:1005— TooManyFunctions — 32 free functions. The bar is 30 free functions; this is 2 over it, 1.07× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
TooManyFunctions: risingwave_expr_impl::scalar::cmp src/expr/impl/src/scalar/cmp.rs:44— TooManyFunctions — 32 free functions. The bar is 30 free functions; this is 2 over it, 1.07× the bar. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility.
D4 · Code Duplication· Members sharing a duplicated core (5 members, 50+ identical tokens) · ×7
Members sharing a duplicated core (5 members, 50+ identical tokens) src/frontend/src/catalog/system_catalog/rw_catalog/rw_connections.rs:37— src/frontend/src/catalog/system_catalog/rw_catalog/rw_connections.rs:37-81 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_functions.rs:41-72 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_materialized_views.rs:43-75 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_secrets.rs:33-56 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_tables.rs:40-70 — These 5 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 5 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 5 times.
Members sharing a duplicated core (5 members, 50+ identical tokens) src/frontend/src/catalog/system_catalog/rw_catalog/rw_internal_tables.rs:39— src/frontend/src/catalog/system_catalog/rw_catalog/rw_internal_tables.rs:39-68 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_sinks.rs:52-116 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_sources.rs:54-120 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_subscriptions.rs:40-74 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_views.rs:36-60 — These 5 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 5 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 5 times.
Members sharing a duplicated core (5 members, 50+ identical tokens) src/frontend/src/optimizer/plan_node/batch_hash_join.rs:105— src/frontend/src/optimizer/plan_node/batch_hash_join.rs:105-123 | src/frontend/src/optimizer/plan_node/batch_lookup_join.rs:129-157 | src/frontend/src/optimizer/plan_node/stream_asof_join.rs:202-237 | src/frontend/src/optimizer/plan_node/stream_delta_join.rs:109-129 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:515-590 — These 5 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 5 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 5 times.
Members sharing a duplicated core (5 members, 50+ identical tokens) src/frontend/src/optimizer/plan_node/generic/file_scan.rs:110— src/frontend/src/optimizer/plan_node/generic/file_scan.rs:110-119 | src/frontend/src/optimizer/plan_node/generic/file_scan.rs:157-166 | src/frontend/src/optimizer/plan_node/generic/file_scan.rs:170-179 | src/frontend/src/optimizer/plan_node/generic/mysql_query.rs:57-66 | src/frontend/src/optimizer/plan_node/generic/postgres_query.rs:59-68 — These 5 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 5 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 5 times.
Members sharing a duplicated core (5 members, 50+ identical tokens) src/frontend/src/optimizer/plan_node/stream_dml.rs:35— src/frontend/src/optimizer/plan_node/stream_dml.rs:35-62 | src/frontend/src/optimizer/plan_node/stream_exchange.rs:109-127 | src/frontend/src/optimizer/plan_node/stream_iceberg_with_pk_index_position_delete_merger.rs:44-66 | src/frontend/src/optimizer/plan_node/stream_sink.rs:188-240 | src/frontend/src/optimizer/plan_node/stream_sync_log_store.rs:39-53 — These 5 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 5 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 5 times.
Members sharing a duplicated core (5 members, 50+ identical tokens) src/meta/src/controller/catalog/mod.rs:1117— src/meta/src/controller/catalog/mod.rs:1117-1127 | src/meta/src/controller/catalog/mod.rs:1276-1283 | src/meta/src/controller/catalog/mod.rs:1309-1319 | src/meta/src/controller/catalog/mod.rs:1321-1330 | src/meta/src/controller/catalog/mod.rs:1332-1342 — These 5 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 5 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 5 times.
Members sharing a duplicated core (5 members, 50+ identical tokens) src/meta/src/hummock/mod.rs:101— src/meta/src/hummock/mod.rs:101-129 | src/meta/src/hummock/mod.rs:135-156 | src/meta/src/hummock/mod.rs:162-192 | src/meta/src/hummock/mod.rs:199-250 | src/meta/src/rpc/metrics.rs:1133-1184 — These 5 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 5 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 5 times.
D4 · Code Duplication· Members sharing a duplicated core (4 members, 50+ identical tokens) · ×7
Members sharing a duplicated core (4 members, 50+ identical tokens) src/batch/executors/src/executor/hop_window.rs:144— src/batch/executors/src/executor/hop_window.rs:144-200 | src/expr/core/src/expr/test_utils.rs:96-191 | src/frontend/src/optimizer/plan_node/generic/hop_window.rs:191-288 | src/stream/src/executor/hop_window.rs:72-224 — These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
Members sharing a duplicated core (4 members, 50+ identical tokens) src/meta/src/controller/catalog/alter_op.rs:39— src/meta/src/controller/catalog/alter_op.rs:39-65 | src/meta/src/controller/catalog/alter_op.rs:286-625 | src/meta/src/controller/catalog/alter_op.rs:824-864 | src/meta/src/controller/catalog/alter_op.rs:870-899 — These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
Members sharing a duplicated core (4 members, 50+ identical tokens) src/risedevtool/src/task/compactor_service.rs:65— src/risedevtool/src/task/compactor_service.rs:65-102 | src/risedevtool/src/task/compute_node_service.rs:67-124 | src/risedevtool/src/task/frontend_service.rs:89-115 | src/risedevtool/src/task/meta_node_service.rs:243-287 — These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
Members sharing a duplicated core (4 members, 50+ identical tokens) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:87— java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:87-120 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/PostgresDialect.java:117-158 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SnowflakeDialect.java:63-109 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SqlServerDialect.java:123-156 — These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
Members sharing a duplicated core (4 members, 50+ identical tokens) e2e_test/s3/file_sink.py:59— e2e_test/s3/file_sink.py:59-156 | e2e_test/s3/file_sink.py:159-374 | e2e_test/s3/file_source.py:332-439 | e2e_test/s3/file_source.py:449-531 — These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
Members sharing a duplicated core (4 members, 50+ identical tokens) e2e_test/webhook/websocket_sender.py:404— e2e_test/webhook/websocket_sender.py:404-465 | e2e_test/webhook/websocket_sender.py:481-510 | e2e_test/webhook/websocket_sender.py:514-543 | e2e_test/webhook/websocket_sender.py:547-574 — These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
Members sharing a duplicated core (4 members, 50+ identical tokens) integration_tests/iceberg-cdc/python/script/init.py:34— integration_tests/iceberg-cdc/python/script/init.py:34-98 | integration_tests/iceberg-sink2/python/main.py:65-112 | integration_tests/iceberg-source/python/main.py:67-87 | integration_tests/iceberg-source/python/main.py:90-107 — These 4 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
Duplicated block (14–15 lines × 2) REDACTED:85— REDACTED:85-98 | REDACTED:314-328 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–15 lines × 2) src/frontend/src/planner/relation.rs:667— src/frontend/src/planner/relation.rs:667-680 | src/frontend/src/planner/relation.rs:696-710 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–15 lines × 2) src/meta/src/controller/streaming_job.rs:2984— src/meta/src/controller/streaming_job.rs:2984-2998 | src/meta/src/controller/streaming_job.rs:3468-3481 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–15 lines × 2) src/meta/src/controller/streaming_job.rs:3098— src/meta/src/controller/streaming_job.rs:3098-3111 | src/meta/src/controller/streaming_job.rs:3168-3182 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–15 lines × 2) src/meta/src/dashboard/mod.rs:580— src/meta/src/dashboard/mod.rs:580-593 | src/meta/src/dashboard/mod.rs:642-656 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–15 lines × 2) src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:281— src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:281-294 | src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:651-665 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–15 lines × 2) src/stream/src/executor/nested_loop_temporal_join.rs:161— src/stream/src/executor/nested_loop_temporal_join.rs:161-175 | src/stream/src/executor/temporal_join.rs:688-701 — before extracting anything, compare `src/stream/src/executor/nested_loop_temporal_join.rs` and `src/stream/src/executor/temporal_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 102 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (14 lines × 3) src/batch/executors/src/executor/join/hash_join.rs:1314— src/batch/executors/src/executor/join/hash_join.rs:1314-1327 | src/batch/executors/src/executor/join/hash_join.rs:1431-1444 | src/batch/executors/src/executor/join/hash_join.rs:1580-1593 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (14 lines × 3) src/common/metrics/src/monitor/process.rs:113— src/common/metrics/src/monitor/process.rs:113-126 | src/common/metrics/src/monitor/process.rs:164-177 | src/common/metrics/src/monitor/process.rs:194-207 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (14 lines × 3) src/expr/macro/src/gen.rs:165— src/expr/macro/src/gen.rs:165-178 | src/expr/macro/src/gen.rs:824-837 | src/expr/macro/src/gen.rs:1162-1175 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (14 lines × 3) src/frontend/src/scheduler/local.rs:333— src/frontend/src/scheduler/local.rs:333-346 | src/frontend/src/scheduler/local.rs:378-391 | src/frontend/src/scheduler/local.rs:416-429 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (14 lines × 3) src/meta/model/migration/src/m20240304_074901_subscription.rs:55— src/meta/model/migration/src/m20240304_074901_subscription.rs:55-68 | src/meta/model/migration/src/m20240506_112555_subscription_partial_ckpt.rs:46-59 | src/meta/model/migration/src/m20240506_112555_subscription_partial_ckpt.rs:107-120 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (14 lines × 3) src/meta/src/dashboard/mod.rs:883— src/meta/src/dashboard/mod.rs:883-896 | src/meta/src/dashboard/mod.rs:910-923 | src/meta/src/dashboard/mod.rs:936-949 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (14 lines × 3) docs/metrics/extract.py:402— docs/metrics/extract.py:402-415 | docs/metrics/extract.py:532-545 | docs/metrics/extract.py:619-632 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (13 lines × 3) src/batch/executors/src/executor/join/hash_join.rs:1259— src/batch/executors/src/executor/join/hash_join.rs:1259-1271 | src/batch/executors/src/executor/join/hash_join.rs:1321-1333 | src/batch/executors/src/executor/join/hash_join.rs:1438-1450 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (13 lines × 3) src/frontend/src/optimizer/plan_node/logical_delete.rs:79— src/frontend/src/optimizer/plan_node/logical_delete.rs:79-91 | src/frontend/src/optimizer/plan_node/logical_insert.rs:105-117 | src/frontend/src/optimizer/plan_node/logical_update.rs:82-94 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (13 lines × 3) src/frontend/src/optimizer/rule/table_function_to_file_scan_rule.rs:44— src/frontend/src/optimizer/rule/table_function_to_file_scan_rule.rs:44-56 | src/frontend/src/optimizer/rule/table_function_to_mysql_query_rule.rs:44-56 | src/frontend/src/optimizer/rule/table_function_to_postgres_query_rule.rs:45-57 — before extracting anything, compare `src/frontend/src/optimizer/rule/table_function_to_mysql_query_rule.rs` and `src/frontend/src/optimizer/rule/table_function_to_postgres_query_rule.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 42 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (13 lines × 3) src/frontend/src/scheduler/local.rs:320— src/frontend/src/scheduler/local.rs:320-332 | src/frontend/src/scheduler/local.rs:363-375 | src/frontend/src/scheduler/local.rs:401-413 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (13 lines × 3) src/frontend/src/handler/create_aggregate.rs:91— src/frontend/src/handler/create_aggregate.rs:91-103 | src/frontend/src/handler/create_function.rs:141-153 | src/frontend/src/handler/create_sql_function.rs:121-133 — before extracting anything, compare `src/frontend/src/handler/create_aggregate.rs` and `src/frontend/src/handler/create_function.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 59 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (13 lines × 3) src/meta/src/rpc/election/sql.rs:223— src/meta/src/rpc/election/sql.rs:223-235 | src/meta/src/rpc/election/sql.rs:398-410 | src/meta/src/rpc/election/sql.rs:573-585 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (13 lines × 3) src/meta/src/rpc/election/sql.rs:202— src/meta/src/rpc/election/sql.rs:202-214 | src/meta/src/rpc/election/sql.rs:377-389 | src/meta/src/rpc/election/sql.rs:552-564 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (12–13 lines × 2) src/frontend/src/binder/relation/mod.rs:296— src/frontend/src/binder/relation/mod.rs:296-308 | src/frontend/src/binder/relation/mod.rs:352-363 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12–13 lines × 2) src/frontend/src/binder/select.rs:459— src/frontend/src/binder/select.rs:459-470 | src/frontend/src/binder/select.rs:503-515 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12–13 lines × 2) src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:48— src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:48-60 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:93-104 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12–13 lines × 2) src/frontend/src/handler/alter_connection_props.rs:48— src/frontend/src/handler/alter_connection_props.rs:48-60 | src/frontend/src/handler/alter_sink_props.rs:58-69 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (12–13 lines × 2) src/frontend/src/handler/alter_streaming_enable_unaligned_join.rs:61— src/frontend/src/handler/alter_streaming_enable_unaligned_join.rs:61-72 | src/frontend/src/handler/describe.rs:309-321 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (12–13 lines × 2) src/sqlparser/src/ast/mod.rs:3065— src/sqlparser/src/ast/mod.rs:3065-3077 | src/sqlparser/src/ast/query.rs:419-430 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (12–13 lines × 2) docs/metrics/extract.py:74— docs/metrics/extract.py:74-85 | docs/metrics/extract.py:134-146 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it.
Duplicated block (12 lines × 3) src/batch/executors/src/executor/delete.rs:179— src/batch/executors/src/executor/delete.rs:179-190 | src/batch/executors/src/executor/insert.rs:190-201 | src/batch/executors/src/executor/update.rs:214-225 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (12 lines × 3) src/batch/executors/src/executor/hop_window.rs:152— src/batch/executors/src/executor/hop_window.rs:152-163 | src/expr/core/src/expr/test_utils.rs:97-108 | src/stream/src/executor/hop_window.rs:84-95 — before extracting anything, compare `src/batch/executors/src/executor/hop_window.rs` and `src/stream/src/executor/hop_window.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (12 lines × 3) src/compute/src/server.rs:516— src/compute/src/server.rs:516-527 | src/storage/compactor/src/server.rs:370-381 | src/storage/compactor/src/server.rs:479-491 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (12 lines × 3) src/frontend/src/optimizer/plan_node/logical_agg.rs:1310— src/frontend/src/optimizer/plan_node/logical_agg.rs:1310-1321 | src/frontend/src/optimizer/plan_node/logical_filter.rs:149-160 | src/frontend/src/optimizer/plan_node/logical_over_window.rs:577-588 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/logical_agg.rs` and `src/frontend/src/optimizer/plan_node/logical_over_window.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 30 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (12 lines × 3) src/frontend/src/optimizer/rule/table_function_to_file_scan_rule.rs:31— src/frontend/src/optimizer/rule/table_function_to_file_scan_rule.rs:31-42 | src/frontend/src/optimizer/rule/table_function_to_mysql_query_rule.rs:30-41 | src/frontend/src/optimizer/rule/table_function_to_postgres_query_rule.rs:31-42 — before extracting anything, compare `src/frontend/src/optimizer/rule/table_function_to_mysql_query_rule.rs` and `src/frontend/src/optimizer/rule/table_function_to_postgres_query_rule.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 42 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (12 lines × 3) src/meta/src/controller/catalog/alter_op.rs:52— src/meta/src/controller/catalog/alter_op.rs:52-63 | src/meta/src/controller/catalog/alter_op.rs:306-317 | src/meta/src/controller/catalog/alter_op.rs:886-897 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (12 lines × 3) src/storage/src/mem_table.rs:180— src/storage/src/mem_table.rs:180-191 | src/storage/src/mem_table.rs:246-257 | src/storage/src/mem_table.rs:348-359 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (11–12 lines × 2) src/connector/src/source/nexmark/source/combined_event.rs:228— src/connector/src/source/nexmark/source/combined_event.rs:228-238 | src/connector/src/source/nexmark/source/combined_event.rs:276-287 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–12 lines × 2) src/ctl/src/cmd_impl/hummock/compaction_group.rs:220— src/ctl/src/cmd_impl/hummock/compaction_group.rs:220-231 | src/ctl/src/cmd_impl/hummock/compaction_group.rs:252-262 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–12 lines × 2) src/expr/impl/src/scalar/to_char.rs:102— src/expr/impl/src/scalar/to_char.rs:102-113 | src/expr/impl/src/scalar/to_char.rs:158-168 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–12 lines × 2) src/meta/src/controller/streaming_job.rs:4063— src/meta/src/controller/streaming_job.rs:4063-4073 | src/meta/src/controller/streaming_job.rs:4132-4143 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–12 lines × 2) src/stream/src/executor/asof_join.rs:206— src/stream/src/executor/asof_join.rs:206-216 | src/stream/src/executor/hash_join.rs:349-360 — before extracting anything, compare `src/stream/src/executor/asof_join.rs` and `src/stream/src/executor/hash_join.rs` as WHOLE FILES: this scan already matched 13 separate duplicated blocks between them, totalling at least 244 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11–12 lines × 2) grafana/dashboard/dev/streaming_fragments.py:61— grafana/dashboard/dev/streaming_fragments.py:61-72 | grafana/dashboard/dev/streaming_relations.py:86-96 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once. Read the line range as the matched WINDOW rather than a finished unit: at `grafana/dashboard/dev/streaming_fragments.py:61` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (11–12 lines × 2) java/java-binding-integration-test/src/main/java/com/risingwave/java/binding/HummockReadDemo.java:87— java/java-binding-integration-test/src/main/java/com/risingwave/java/binding/HummockReadDemo.java:87-97 | java/java-binding-integration-test/src/main/java/com/risingwave/java/binding/StreamChunkDemo.java:32-43 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once. Read the line range as the matched WINDOW rather than a finished unit: at `java/java-binding-integration-test/src/main/java/com/risingwave/java/binding/HummockReadDemo.java:87` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (11 lines × 3) src/common/src/array/arrow/arrow_iceberg.rs:131— src/common/src/array/arrow/arrow_iceberg.rs:131-141 | src/common/src/array/arrow/arrow_iceberg.rs:501-511 | src/common/src/array/arrow/arrow_impl.rs:362-372 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (11 lines × 3) src/expr/impl/src/udf/wasm.rs:59— src/expr/impl/src/udf/wasm.rs:59-69 | src/expr/impl/src/udf/wasm.rs:147-157 | src/expr/impl/src/udf/wasm.rs:186-196 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (11 lines × 3) src/frontend/src/optimizer/plan_node/batch_delete.rs:69— src/frontend/src/optimizer/plan_node/batch_delete.rs:69-79 | src/frontend/src/optimizer/plan_node/batch_insert.rs:81-91 | src/frontend/src/optimizer/plan_node/batch_update.rs:72-82 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (11 lines × 3) src/frontend/src/handler/alter_set_schema.rs:84— src/frontend/src/handler/alter_set_schema.rs:84-94 | src/frontend/src/handler/alter_set_schema.rs:100-111 | src/frontend/src/handler/alter_set_schema.rs:117-128 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (11 lines × 3) src/meta/src/hummock/manager/compaction/compaction_group_manager.rs:302— src/meta/src/hummock/manager/compaction/compaction_group_manager.rs:302-312 | src/meta/src/hummock/manager/compaction/compaction_group_schedule/normalize.rs:203-213 | src/meta/src/hummock/manager/versioning.rs:319-329 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (11 lines × 3) src/stream/src/from_proto/lookup.rs:77— src/stream/src/from_proto/lookup.rs:77-87 | src/stream/src/from_proto/temporal_join.rs:95-105 | src/stream/src/from_proto/temporal_join.rs:179-189 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (11 lines × 3) docs/metrics/extract.py:553— docs/metrics/extract.py:553-563 | docs/metrics/extract.py:588-598 | docs/metrics/extract.py:635-645 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just after the matched lines, `docs/metrics/extract.py:646` calls `extract_labels` and `docs/metrics/extract.py:564` does not — after which the two agree again for 3 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
Duplicated block (7 lines × 3) src/batch/executors/src/executor/hash_agg.rs:412— src/batch/executors/src/executor/hash_agg.rs:412-418 | src/batch/executors/src/executor/hash_agg.rs:439-445 | src/batch/executors/src/executor/order_by.rs:404-410 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/order_by.rs` as WHOLE FILES: this scan already matched 7 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (7 lines × 3) src/batch/executors/src/executor/join/hash_join.rs:1256— src/batch/executors/src/executor/join/hash_join.rs:1256-1262 | src/batch/executors/src/executor/join/hash_join.rs:1387-1393 | src/batch/executors/src/executor/join/hash_join.rs:1505-1511 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (7 lines × 3) src/batch/src/task/broadcast_channel.rs:94— src/batch/src/task/broadcast_channel.rs:94-100 | src/batch/src/task/consistent_hash_shuffle_channel.rs:175-181 | src/batch/src/task/hash_shuffle_channel.rs:164-170 — before extracting anything, compare `src/batch/src/task/consistent_hash_shuffle_channel.rs` and `src/batch/src/task/hash_shuffle_channel.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (7 lines × 3) src/frontend/src/catalog/system_catalog/rw_catalog/rw_internal_tables.rs:62— src/frontend/src/catalog/system_catalog/rw_catalog/rw_internal_tables.rs:62-68 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_subscriptions.rs:66-74 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_tables.rs:64-70 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (7 lines × 3) src/frontend/src/optimizer/plan_node/stream_exchange.rs:115— src/frontend/src/optimizer/plan_node/stream_exchange.rs:115-121 | src/frontend/src/optimizer/plan_node/stream_iceberg_with_pk_index_position_delete_merger.rs:54-60 | src/frontend/src/optimizer/plan_node/stream_sync_log_store.rs:44-50 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (7 lines × 3) src/stream/src/executor/join/asof_join.rs:484— src/stream/src/executor/join/asof_join.rs:484-490 | src/stream/src/executor/join/asof_join.rs:544-550 | src/stream/src/executor/join/asof_join.rs:667-673 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (7 lines × 3) src/connector/src/sink/starrocks.rs:585— src/connector/src/sink/starrocks.rs:585-591 | src/connector/src/sink/starrocks.rs:596-602 | src/connector/src/sink/starrocks.rs:608-614 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Condition::analyze_group (cognitive 66) src/frontend/src/utils/condition.rs:843— Condition::analyze_group has cognitive complexity 66 (threshold 15). Drivers by points: if/else 19 (45 pts), match/switch 4 (16 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 40). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Condition::disjunctions_to_scan_ranges (cognitive 63) src/frontend/src/utils/condition.rs:323— Condition::disjunctions_to_scan_ranges has cognitive complexity 63 (threshold 15). Drivers by points: if/else 18 (39 pts), match/switch 4 (12 pts), boolean chains 6, loops 3 (6 pts) (nesting depth added 32). Of this number, 47 points are the body's own statements and 16 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Condition::split_row_cmp_to_scan_ranges (cognitive 50) src/frontend/src/utils/condition.rs:531— Condition::split_row_cmp_to_scan_ranges has cognitive complexity 50 (threshold 15). Drivers by points: if/else 13 (33 pts), match/switch 3 (11 pts), boolean chains 3, loops 1 (3 pts) (nesting depth added 30). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
Condition::split_to_scan_ranges (cognitive 37) src/frontend/src/utils/condition.rs:665— Condition::split_to_scan_ranges has cognitive complexity 37 (threshold 15). Drivers by points: if/else 16 (28 pts), match/switch 3 (7 pts), boolean chains 1, loops 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Condition::extract_eq_conds_within_range (cognitive 20) src/frontend/src/utils/condition.rs:1065— Condition::extract_eq_conds_within_range has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (15 pts), match/switch 2 (4 pts), boolean chains 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Condition::split_by_input_col_nums (cognitive 16) src/frontend/src/utils/condition.rs:173— Condition::split_by_input_col_nums has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (10 pts), loops 3 (4 pts), boolean chains 2 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (17–18 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:803— src/batch/executors/src/executor/join/hash_join.rs:803-820 | src/batch/executors/src/executor/join/hash_join.rs:885-901 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17–18 lines × 2) src/frontend/src/handler/create_table.rs:599— src/frontend/src/handler/create_table.rs:599-615 | src/frontend/src/handler/create_table.rs:867-884 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17–18 lines × 2) src/frontend/src/optimizer/plan_node/logical_multi_join.rs:371— src/frontend/src/optimizer/plan_node/logical_multi_join.rs:371-387 | src/frontend/src/optimizer/plan_node/logical_multi_join.rs:643-660 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17–18 lines × 2) src/frontend/src/optimizer/plan_node/stream_project.rs:109— src/frontend/src/optimizer/plan_node/stream_project.rs:109-125 | src/frontend/src/optimizer/plan_node/stream_project_set.rs:71-88 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (17–18 lines × 2) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:313— src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:313-330 | src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:881-897 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (17–18 lines × 2) src/stream/src/executor/top_n/top_n_state.rs:179— src/stream/src/executor/top_n/top_n_state.rs:179-196 | src/stream/src/executor/top_n/top_n_state.rs:283-299 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15–16 lines × 2) src/batch/executors/src/executor/log_row_seq_scan.rs:107— src/batch/executors/src/executor/log_row_seq_scan.rs:107-122 | src/batch/executors/src/executor/row_seq_scan.rs:97-111 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (15–16 lines × 2) src/frontend/src/handler/create_function.rs:100— src/frontend/src/handler/create_function.rs:100-114 | src/frontend/src/handler/create_sql_function.rs:81-96 — before extracting anything, compare `src/frontend/src/handler/create_function.rs` and `src/frontend/src/handler/create_sql_function.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (15–16 lines × 2) src/frontend/src/handler/alter_rename.rs:204— src/frontend/src/handler/alter_rename.rs:204-219 | src/frontend/src/handler/alter_source_props.rs:142-156 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (15–16 lines × 2) src/meta/src/hummock/compaction/picker/intra_compaction_picker.rs:374— src/meta/src/hummock/compaction/picker/intra_compaction_picker.rs:374-389 | src/meta/src/hummock/compaction/picker/tier_compaction_picker.rs:97-111 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (15–16 lines × 2) src/stream/src/from_proto/source/trad_source.rs:178— src/stream/src/from_proto/source/trad_source.rs:178-192 | src/stream/src/from_proto/source_backfill.rs:46-61 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (15–16 lines × 2) src/stream/src/task/barrier_worker/managed_state.rs:1237— src/stream/src/task/barrier_worker/managed_state.rs:1237-1252 | src/stream/src/task/barrier_worker/managed_state.rs:1255-1269 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13–14 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:1271— src/batch/executors/src/executor/join/hash_join.rs:1271-1284 | src/batch/executors/src/executor/join/hash_join.rs:1521-1533 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13–14 lines × 2) src/expr/core/src/error.rs:161— src/expr/core/src/error.rs:161-173 | src/expr/impl/src/scalar/string.rs:500-513 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (13–14 lines × 2) src/expr/impl/src/scalar/string.rs:129— src/expr/impl/src/scalar/string.rs:129-141 | src/expr/impl/src/scalar/string.rs:204-217 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13–14 lines × 2) src/frontend/src/datafusion/aggregate/single_phase.rs:134— src/frontend/src/datafusion/aggregate/single_phase.rs:134-147 | src/frontend/src/datafusion/aggregate/two_phase.rs:138-150 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (13–14 lines × 2) src/frontend/src/handler/alter_streaming_enable_unaligned_join.rs:30— src/frontend/src/handler/alter_streaming_enable_unaligned_join.rs:30-42 | src/frontend/src/handler/describe.rs:277-290 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (13–14 lines × 2) src/stream/src/executor/mview/cache.rs:223— src/stream/src/executor/mview/cache.rs:223-235 | src/stream/src/executor/mview/cache.rs:290-303 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10–11 lines × 2) src/frontend/src/handler/create_mv.rs:401— src/frontend/src/handler/create_mv.rs:401-410 | src/frontend/src/handler/create_sink.rs:522-532 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (10–11 lines × 2) src/frontend/src/optimizer/rule/pull_up_correlated_predicate_agg_rule.rs:97— src/frontend/src/optimizer/rule/pull_up_correlated_predicate_agg_rule.rs:97-106 | src/frontend/src/optimizer/rule/pull_up_correlated_predicate_rule.rs:67-77 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (10–11 lines × 2) src/meta/src/barrier/checkpoint/control.rs:890— src/meta/src/barrier/checkpoint/control.rs:890-899 | src/meta/src/barrier/checkpoint/control.rs:904-914 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10–11 lines × 2) src/storage/src/table/batch_table/mod.rs:347— src/storage/src/table/batch_table/mod.rs:347-357 | src/stream/src/common/table/state_table.rs:1098-1107 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (10–11 lines × 2) src/stream/src/executor/backfill/cdc/cdc_backfill.rs:341— src/stream/src/executor/backfill/cdc/cdc_backfill.rs:341-351 | src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:118-127 — before extracting anything, compare `src/stream/src/executor/backfill/cdc/cdc_backfill.rs` and `src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 38 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10–11 lines × 2) java/connector-node/python-client/pyspark-util.py:78— java/connector-node/python-client/pyspark-util.py:78-87 | java/connector-node/python-client/pyspark-util.py:107-117 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6 lines × 3) src/connector/src/connector_common/iceberg/jni_catalog.rs:188— src/connector/src/connector_common/iceberg/jni_catalog.rs:188-193 | src/connector/src/connector_common/iceberg/jni_catalog.rs:240-245 | src/connector/src/connector_common/iceberg/jni_catalog.rs:272-277 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (6 lines × 3) src/connector/src/source/cdc/external/postgres.rs:421— src/connector/src/source/cdc/external/postgres.rs:421-426 | src/connector/src/source/cdc/external/postgres.rs:444-449 | src/connector/src/source/cdc/external/postgres.rs:455-460 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (6 lines × 3) src/frontend/src/session.rs:1222— src/frontend/src/session.rs:1222-1227 | src/frontend/src/session.rs:1267-1272 | src/frontend/src/session.rs:1315-1320 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (6 lines × 3) src/stream/src/executor/dml.rs:199— src/stream/src/executor/dml.rs:199-204 | src/stream/src/executor/source/fs_fetch_executor.rs:443-448 | src/stream/src/executor/source/iceberg_fetch_executor.rs:391-396 — before extracting anything, compare `src/stream/src/executor/source/fs_fetch_executor.rs` and `src/stream/src/executor/source/iceberg_fetch_executor.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 71 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (6 lines × 3) src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs:157— src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs:157-162 | src/frontend/src/optimizer/plan_node/generic/sys_scan.rs:52-57 | src/frontend/src/optimizer/plan_node/generic/table_scan.rs:171-176 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs` and `src/frontend/src/optimizer/plan_node/generic/table_scan.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 41 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (6 lines × 3) src/compute/src/telemetry.rs:61— src/compute/src/telemetry.rs:61-66 | src/frontend/src/telemetry.rs:82-87 | src/storage/compactor/src/telemetry.rs:77-82 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
risingwave_expr_impl::scalar::to_char::format_inner (cyclomatic 36) src/expr/impl/src/scalar/to_char.rs:244— risingwave_expr_impl::scalar::to_char::format_inner has cyclomatic complexity 36 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_expr_impl::scalar::regexp::regexp_replace (cyclomatic 20) src/expr/impl/src/scalar/regexp.rs:271— risingwave_expr_impl::scalar::regexp::regexp_replace has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_expr_impl::scalar::similar_to_escape::similar_escape_internal (cyclomatic 16) src/expr/impl/src/scalar/similar_to_escape.rs:20— risingwave_expr_impl::scalar::similar_to_escape::similar_escape_internal has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_expr_impl::scalar::jsonb_set::jsonbb_set_path (cyclomatic 16) src/expr/impl/src/scalar/jsonb_set.rs:75— risingwave_expr_impl::scalar::jsonb_set::jsonbb_set_path has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_expr_impl::scalar::array_concat::array_cat (cyclomatic 16) src/expr/impl/src/scalar/array_concat.rs:91— risingwave_expr_impl::scalar::array_concat::array_cat has cyclomatic complexity 16 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
risingwave_stream::executor::barrier_align::barrier_align (cyclomatic 23) src/stream/src/executor/barrier_align.rs:45— risingwave_stream::executor::barrier_align::barrier_align has cyclomatic complexity 23 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_stream::executor::temporal_join::phase1::handle_chunk (cyclomatic 23) src/stream/src/executor/temporal_join.rs:448— risingwave_stream::executor::temporal_join::phase1::handle_chunk has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_stream::executor::lookup::sides::align_barrier (cyclomatic 20) src/stream/src/executor/lookup/sides.rs:124— risingwave_stream::executor::lookup::sides::align_barrier has cyclomatic complexity 20 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_stream::executor::lookup::sides::stream_lookup_arrange_this_epoch (cyclomatic 20) src/stream/src/executor/lookup/sides.rs:299— risingwave_stream::executor::lookup::sides::stream_lookup_arrange_this_epoch has cyclomatic complexity 20 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_stream::executor::backfill::snapshot_backfill::executor::make_consume_snapshot_stream (cyclomatic 16) src/stream/src/executor/backfill/snapshot_backfill/executor.rs:1015— risingwave_stream::executor::backfill::snapshot_backfill::executor::make_consume_snapshot_stream has cyclomatic complexity 16 (threshold 15). Of this number, 14 points are the body's own statements and 2 belong to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Duplicated block (30 lines × 2) src/connector/src/sink/iceberg/writer.rs:834— src/connector/src/sink/iceberg/writer.rs:834-863 | src/connector/src/sink/iceberg/writer.rs:868-897 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (30 lines × 2) src/meta/src/barrier/backfill_order_control.rs:95— src/meta/src/barrier/backfill_order_control.rs:95-124 | src/meta/src/barrier/backfill_order_control.rs:162-191 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (30 lines × 2) src/stream/src/executor/dynamic_filter.rs:144— src/stream/src/executor/dynamic_filter.rs:144-173 | src/stream/src/executor/filter.rs:113-142 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (30 lines × 2) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:91— java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:91-120 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SqlServerDialect.java:127-156 — before extracting anything, compare `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java` and `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SqlServerDialect.java` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:91` it runs out through the closing brace of the declaration holding it — the window is that declaration's tail, not a fragment that begins part-way through something, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (30 lines × 2) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java:116— java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java:116-145 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/JDBCSink.java:116-145 — before extracting anything, compare `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java` and `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/JDBCSink.java` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 97 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Each matched range is the entire body of the declaration above it, so the region is already a complete unit: move that whole declaration to the shared location and have each site call it, rather than lifting the lines out of their bodies. Any `return` inside it is the body's own exit and keeps its meaning in the moved unit.
Duplicated block (25 lines × 2) src/compute/src/rpc/service/monitor_service.rs:422— src/compute/src/rpc/service/monitor_service.rs:422-446 | src/compute/src/rpc/service/monitor_service.rs:449-473 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (25 lines × 2) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:364— src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:364-388 | src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:952-976 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (25 lines × 2) src/stream/src/executor/gap_fill.rs:606— src/stream/src/executor/gap_fill.rs:606-630 | src/stream/src/executor/gap_fill.rs:699-723 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (25 lines × 2) src/stream/src/executor/mview/materialize.rs:469— src/stream/src/executor/mview/materialize.rs:469-493 | src/stream/src/executor/mview/materialize.rs:534-558 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (25 lines × 2) src/meta/src/rpc/election/sql.rs:165— src/meta/src/rpc/election/sql.rs:165-189 | src/meta/src/rpc/election/sql.rs:510-539 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:1002— src/batch/executors/src/executor/join/hash_join.rs:1002-1021 | src/batch/executors/src/executor/join/hash_join.rs:1621-1640 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20 lines × 2) src/connector/src/parser/config.rs:198— src/connector/src/parser/config.rs:198-217 | src/connector/src/parser/config.rs:241-260 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20 lines × 2) src/meta/src/stream/scale.rs:523— src/meta/src/stream/scale.rs:523-542 | src/meta/src/stream/scale.rs:577-596 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20 lines × 2) src/storage/hummock_sdk/src/sstable_info.rs:262— src/storage/hummock_sdk/src/sstable_info.rs:262-281 | src/storage/hummock_sdk/src/sstable_info.rs:312-331 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20 lines × 2) java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/ElasticBulkProcessorAdapter.java:43— java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/ElasticBulkProcessorAdapter.java:43-62 | java/connector-node/risingwave-sink-es-7/src/main/java/com/risingwave/connector/OpensearchBulkProcessorAdapter.java:43-62 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once. Note first that the copies are not typed on the same thing: `BackoffPolicy` names `org.elasticsearch.action.bulk.BackoffPolicy` in one and `org.opensearch.action.bulk.BackoffPolicy` in another — different types that share a simple name, which is why the text matched. A single extracted unit cannot be given a parameter type that fits both, so unifying those types (or introducing a shared abstraction over them) is the step that has to come BEFORE the extraction above; if they are deliberately separate, the duplication is the price of that separation and the honest resolution is to record the decision rather than to extract.
Duplicated block (11–13 lines × 2) src/connector/src/sink/iceberg/writer.rs:377— src/connector/src/sink/iceberg/writer.rs:377-389 | src/connector/src/sink/iceberg/writer.rs:511-521 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–13 lines × 2) src/connector/src/sink/snowflake_redshift/snowflake.rs:1181— src/connector/src/sink/snowflake_redshift/snowflake.rs:1181-1193 | src/connector/src/sink/snowflake_redshift/snowflake.rs:1204-1214 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–13 lines × 2) src/frontend/src/optimizer/plan_node/stream_materialize.rs:689— src/frontend/src/optimizer/plan_node/stream_materialize.rs:689-701 | src/frontend/src/optimizer/plan_node/stream_vector_index_write.rs:243-253 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (11–13 lines × 2) src/meta/src/controller/streaming_job.rs:2877— src/meta/src/controller/streaming_job.rs:2877-2889 | src/meta/src/controller/streaming_job.rs:3504-3514 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–13 lines × 2) src/storage/src/memory.rs:165— src/storage/src/memory.rs:165-175 | src/storage/src/memory.rs:197-209 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6–7 lines × 2) src/batch/executors/src/executor/join/nested_loop_join.rs:286— src/batch/executors/src/executor/join/nested_loop_join.rs:286-292 | src/batch/executors/src/executor/join/nested_loop_join.rs:461-466 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6–7 lines × 2) src/frontend/src/handler/query.rs:90— src/frontend/src/handler/query.rs:90-95 | src/frontend/src/handler/query.rs:107-113 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6–7 lines × 2) src/meta/src/controller/streaming_job.rs:3129— src/meta/src/controller/streaming_job.rs:3129-3134 | src/meta/src/controller/streaming_job.rs:3223-3229 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6–7 lines × 2) src/meta/src/controller/catalog/util.rs:107— src/meta/src/controller/catalog/util.rs:107-112 | src/meta/src/controller/catalog/util.rs:131-137 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (6–7 lines × 2) src/stream/src/executor/join/asof_join.rs:589— src/stream/src/executor/join/asof_join.rs:589-595 | src/stream/src/executor/join/asof_join.rs:622-627 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
risingwave_ctl::start_impl (cyclomatic 61) src/ctl/src/lib.rs:666— risingwave_ctl::start_impl has cyclomatic complexity 61 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_ctl::cmd_impl::hummock::compaction_group::build_compaction_config_vec (cyclomatic 31) src/ctl/src/cmd_impl/hummock/compaction_group.rs:53— risingwave_ctl::cmd_impl::hummock::compaction_group::build_compaction_config_vec has cyclomatic complexity 31 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
risingwave_ctl::cmd_impl::meta::reschedule::unregister_workers (cyclomatic 19) src/ctl/src/cmd_impl/meta/reschedule.rs:183— risingwave_ctl::cmd_impl::meta::reschedule::unregister_workers has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_ctl::cmd_impl::meta::cluster_info::source_split_info (cyclomatic 16) src/ctl/src/cmd_impl/meta/cluster_info.rs:35— risingwave_ctl::cmd_impl::meta::cluster_info::source_split_info has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
FunctionAttr::generate_build_scalar_function (cyclomatic 39) src/expr/macro/src/gen.rs:198— FunctionAttr::generate_build_scalar_function has cyclomatic complexity 39 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
FunctionAttr::generate_agg_build_fn (cyclomatic 32) src/expr/macro/src/gen.rs:859— FunctionAttr::generate_agg_build_fn has cyclomatic complexity 32 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
FunctionAttr::parse (cyclomatic 19) src/expr/macro/src/parse.rs:27— FunctionAttr::parse has cyclomatic complexity 19 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
FunctionAttr::generate_build_table_function (cyclomatic 16) src/expr/macro/src/gen.rs:1191— FunctionAttr::generate_build_table_function has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Condition::disjunctions_to_scan_ranges (cyclomatic 28) src/frontend/src/utils/condition.rs:323— Condition::disjunctions_to_scan_ranges has cyclomatic complexity 28 (threshold 15). Of this number, 22 points are the body's own statements and 6 belong to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Condition::analyze_group (cyclomatic 28) src/frontend/src/utils/condition.rs:843— Condition::analyze_group has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Condition::split_row_cmp_to_scan_ranges (cyclomatic 20) src/frontend/src/utils/condition.rs:531— Condition::split_row_cmp_to_scan_ranges has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Condition::split_to_scan_ranges (cyclomatic 20) src/frontend/src/utils/condition.rs:665— Condition::split_to_scan_ranges has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
FunctionAttr::generate_agg_build_fn (cognitive 37) src/expr/macro/src/gen.rs:859— FunctionAttr::generate_agg_build_fn has cognitive complexity 37 (threshold 15). Drivers by points: if/else 19 (21 pts), match/switch 8 (11 pts), boolean chains 5 (nesting depth added 5). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
FunctionAttr::generate_build_scalar_function (cognitive 36) src/expr/macro/src/gen.rs:198— FunctionAttr::generate_build_scalar_function has cognitive complexity 36 (threshold 15). Drivers by points: if/else 17 (18 pts), match/switch 13 (14 pts), boolean chains 4 (nesting depth added 2). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
FunctionAttr::parse (cognitive 23) src/expr/macro/src/parse.rs:27— FunctionAttr::parse has cognitive complexity 23 (threshold 15). Drivers by points: if/else 16 (19 pts), match/switch 2, boolean chains 1, loops 1 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
FunctionAttr::generate_type_infer_fn (cognitive 20) src/expr/macro/src/gen.rs:80— FunctionAttr::generate_type_infer_fn has cognitive complexity 20 (threshold 15). Drivers by points: if/else 13 (20 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalJoin::to_batch_lookup_join_with_index_selection (cognitive 25) src/frontend/src/optimizer/plan_node/logical_join.rs:266— LogicalJoin::to_batch_lookup_join_with_index_selection has cognitive complexity 25 (threshold 15). Drivers by points: if/else 7 (17 pts), match/switch 2 (6 pts), loops 1 (2 pts) (nesting depth added 15). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
LogicalJoin::simplify_outer (cognitive 24) src/frontend/src/optimizer/plan_node/logical_join.rs:222— LogicalJoin::simplify_outer has cognitive complexity 24 (threshold 15). Drivers by points: if/else 4 (14 pts), loops 2 (5 pts), match/switch 3 (5 pts) (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalJoin::logical_rewrite_for_stream (cognitive 24) src/frontend/src/optimizer/plan_node/logical_join.rs:1702— LogicalJoin::logical_rewrite_for_stream has cognitive complexity 24 (threshold 15). Drivers by points: if/else 12 (21 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalJoin::to_stream_temporal_join_with_index_selection (cognitive 23) src/frontend/src/optimizer/plan_node/logical_join.rs:1142— LogicalJoin::to_stream_temporal_join_with_index_selection has cognitive complexity 23 (threshold 15). Drivers by points: if/else 5 (15 pts), match/switch 1 (5 pts), loops 1 (2 pts), boolean chains 1 (nesting depth added 15). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
PgProtocol::run (cognitive 21) src/utils/pgwire/src/pg_protocol.rs:296— PgProtocol::run has cognitive complexity 21 (threshold 15). Drivers by points: if/else 5 (11 pts), match/switch 2 (5 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PgProtocol::do_process_inner (cognitive 21) src/utils/pgwire/src/pg_protocol.rs:580— PgProtocol::do_process_inner has cognitive complexity 21 (threshold 15). Drivers by points: if/else 10 (17 pts), match/switch 2 (3 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PgProtocol::inner_process_query_msg_one_stmt (cognitive 20) src/utils/pgwire/src/pg_protocol.rs:874— PgProtocol::inner_process_query_msg_one_stmt has cognitive complexity 20 (threshold 15). Drivers by points: loops 6 (12 pts), if/else 5, match/switch 1 (2 pts), boolean chains 1 (nesting depth added 7). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
PgProtocol::do_process (cognitive 18) src/utils/pgwire/src/pg_protocol.rs:400— PgProtocol::do_process has cognitive complexity 18 (threshold 15). Drivers by points: if/else 8 (11 pts), match/switch 3 (5 pts), boolean chains 1, loops 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risedev::bin::risedev-dev::task_main (cognitive 20) src/risedevtool/src/bin/risedev-dev.rs:66— risedev::bin::risedev-dev::task_main has cognitive complexity 20 (threshold 15). Drivers by points: if/else 8 (16 pts), loops 2, match/switch 1 (2 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risedev::risedev_env::generate_risedev_env (cognitive 19) src/risedevtool/src/risedev_env.rs:25— risedev::risedev_env::generate_risedev_env has cognitive complexity 19 (threshold 15). Drivers by points: if/else 5 (15 pts), match/switch 1 (2 pts), boolean chains 1, loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risedev::bin::risedev-docslt::extract_slt (cognitive 18) src/risedevtool/src/bin/risedev-docslt.rs:35— risedev::bin::risedev-docslt::extract_slt has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (14 pts), loops 2 (3 pts), boolean chains 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risedev::wait::wait (cognitive 17) src/risedevtool/src/wait.rs:24— risedev::wait::wait has cognitive complexity 17 (threshold 15). Drivers by points: if/else 6 (12 pts), boolean chains 2, match/switch 1 (2 pts), loops 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (23 lines × 2) src/batch/src/task/consistent_hash_shuffle_channel.rs:79— src/batch/src/task/consistent_hash_shuffle_channel.rs:79-101 | src/batch/src/task/hash_shuffle_channel.rs:75-97 — before extracting anything, compare `src/batch/src/task/consistent_hash_shuffle_channel.rs` and `src/batch/src/task/hash_shuffle_channel.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (23 lines × 2) src/meta/model/migration/src/m20240820_081248_add_time_travel_per_table_epoch.rs:55— src/meta/model/migration/src/m20240820_081248_add_time_travel_per_table_epoch.rs:55-77 | src/meta/model/migration/src/m20240820_081248_add_time_travel_per_table_epoch.rs:151-173 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (23 lines × 2) src/storage/src/table/batch_table/mod.rs:631— src/storage/src/table/batch_table/mod.rs:631-653 | src/storage/src/table/batch_table/mod.rs:1410-1432 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (23 lines × 2) src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:164— src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:164-186 | src/stream/src/executor/source/fs_list_executor.rs:106-128 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (18–19 lines × 2) src/batch/executors/src/executor/join/nested_loop_join.rs:393— src/batch/executors/src/executor/join/nested_loop_join.rs:393-410 | src/batch/executors/src/executor/join/nested_loop_join.rs:479-497 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18–19 lines × 2) src/batch/executors/src/executor/project_set.rs:83— src/batch/executors/src/executor/project_set.rs:83-101 | src/frontend/src/datafusion/project_set.rs:312-329 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (18–19 lines × 2) src/frontend/src/optimizer/plan_node/logical_project.rs:375— src/frontend/src/optimizer/plan_node/logical_project.rs:375-392 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:376-394 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/logical_project.rs` and `src/frontend/src/optimizer/plan_node/logical_project_set.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 62 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (18–19 lines × 2) src/frontend/src/optimizer/plan_node/logical_scan.rs:243— src/frontend/src/optimizer/plan_node/logical_scan.rs:243-261 | src/frontend/src/optimizer/rule/top_n_on_index_rule.rs:101-118 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (16–17 lines × 2) src/frontend/src/metrics_reader.rs:155— src/frontend/src/metrics_reader.rs:155-170 | src/meta/src/dashboard/mod.rs:924-940 — before extracting anything, compare `src/frontend/src/metrics_reader.rs` and `src/meta/src/dashboard/mod.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 42 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (16–17 lines × 2) src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs:452— src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs:452-467 | src/meta/src/barrier/checkpoint/state.rs:207-223 — before extracting anything, compare `src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs` and `src/meta/src/barrier/checkpoint/state.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 52 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (16–17 lines × 2) src/storage/src/hummock/utils.rs:436— src/storage/src/hummock/utils.rs:436-451 | src/storage/src/hummock/utils.rs:480-496 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16–17 lines × 2) REDACTED:72— REDACTED:72-87 | REDACTED:228-244 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at `REDACTED:72` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (11 lines × 4) src/batch/executors/src/executor/join/hash_join.rs:967— src/batch/executors/src/executor/join/hash_join.rs:967-977 | src/batch/executors/src/executor/join/hash_join.rs:1318-1328 | src/batch/executors/src/executor/join/hash_join.rs:1435-1445 | src/batch/executors/src/executor/join/hash_join.rs:1584-1594 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (11 lines × 4) src/frontend/src/utils/overwrite_options.rs:37— src/frontend/src/utils/overwrite_options.rs:37-47 | src/frontend/src/utils/overwrite_options.rs:50-60 | src/frontend/src/utils/overwrite_options.rs:63-73 | src/frontend/src/utils/overwrite_options.rs:74-85 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (11 lines × 4) src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs:201— src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs:201-211 | src/frontend/src/optimizer/plan_node/generic/log_scan.rs:122-132 | src/frontend/src/optimizer/plan_node/generic/sys_scan.rs:94-104 | src/frontend/src/optimizer/plan_node/generic/table_scan.rs:361-371 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs` and `src/frontend/src/optimizer/plan_node/generic/table_scan.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 41 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11 lines × 4) e2e_test/s3/file_sink.py:141— e2e_test/s3/file_sink.py:141-151 | e2e_test/s3/file_sink.py:355-365 | e2e_test/s3/file_source.py:406-416 | e2e_test/s3/file_source.py:513-523 — there are 4 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 4 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (10 lines × 4) src/batch/executors/src/executor/hop_window.rs:154— src/batch/executors/src/executor/hop_window.rs:154-163 | src/expr/core/src/expr/test_utils.rs:99-108 | src/frontend/src/optimizer/plan_node/generic/hop_window.rs:201-210 | src/stream/src/executor/hop_window.rs:86-95 — before extracting anything, compare `src/batch/executors/src/executor/hop_window.rs` and `src/stream/src/executor/hop_window.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 4) src/batch/executors/src/executor/join/hash_join.rs:873— src/batch/executors/src/executor/join/hash_join.rs:873-882 | src/batch/executors/src/executor/join/hash_join.rs:970-979 | src/batch/executors/src/executor/join/hash_join.rs:1181-1190 | src/batch/executors/src/executor/join/hash_join.rs:1508-1517 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10 lines × 4) src/stream/src/executor/asof_join.rs:433— src/stream/src/executor/asof_join.rs:433-442 | src/stream/src/executor/asof_join.rs:459-468 | src/stream/src/executor/hash_join.rs:699-708 | src/stream/src/executor/hash_join.rs:727-736 — before extracting anything, compare `src/stream/src/executor/asof_join.rs` and `src/stream/src/executor/hash_join.rs` as WHOLE FILES: this scan already matched 13 separate duplicated blocks between them, totalling at least 244 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 4) src/stream/src/executor/dml.rs:230— src/stream/src/executor/dml.rs:230-239 | src/stream/src/executor/dml.rs:273-282 | src/stream/src/executor/dml.rs:298-307 | src/stream/src/executor/sink.rs:679-688 — there are 4 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 4 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (8 lines × 4) src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:116— src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:116-123 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:137-144 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:158-165 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_relation_info.rs:180-188 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8 lines × 4) src/frontend/src/handler/alter_rename.rs:91— src/frontend/src/handler/alter_rename.rs:91-98 | src/frontend/src/handler/alter_rename.rs:120-127 | src/frontend/src/handler/alter_rename.rs:150-157 | src/frontend/src/handler/alter_rename.rs:181-188 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8 lines × 4) src/common/src/array/bool_array.rs:52— src/common/src/array/bool_array.rs:52-59 | src/common/src/array/bytes_array.rs:115-122 | src/common/src/array/num256_array.rs:157-164 | src/common/src/array/primitive_array.rs:143-150 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 4 call sites, so a change lands once.
Duplicated block (8 lines × 4) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:88— java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:88-95 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/PostgresDialect.java:118-125 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SnowflakeDialect.java:64-71 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SqlServerDialect.java:124-131 — before extracting anything, compare `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java` and `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/SqlServerDialect.java` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 64 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/jdbc/MySqlDialect.java:88` it does not close everything it opens, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it.
Duplicated block (5 lines × 4) src/risedevtool/src/bin/risedev-dev.rs:185— src/risedevtool/src/bin/risedev-dev.rs:185-190 | src/risedevtool/src/bin/risedev-dev.rs:195-199 | src/risedevtool/src/bin/risedev-dev.rs:206-210 | src/risedevtool/src/bin/risedev-dev.rs:215-219 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 4) src/storage/src/mem_table.rs:231— src/storage/src/mem_table.rs:231-235 | src/storage/src/mem_table.rs:266-270 | src/storage/src/mem_table.rs:317-321 | src/storage/src/mem_table.rs:332-336 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 4) src/frontend/src/optimizer/plan_node/batch_delete.rs:98— src/frontend/src/optimizer/plan_node/batch_delete.rs:98-102 | src/frontend/src/optimizer/plan_node/batch_insert.rs:128-132 | src/frontend/src/optimizer/plan_node/batch_max_one_row.rs:84-88 | src/frontend/src/optimizer/plan_node/batch_update.rs:111-115 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 4 call sites, so a change lands once.
Duplicated block (5 lines × 4) src/frontend/src/optimizer/plan_node/logical_delete.rs:109— src/frontend/src/optimizer/plan_node/logical_delete.rs:109-113 | src/frontend/src/optimizer/plan_node/logical_filter.rs:197-201 | src/frontend/src/optimizer/plan_node/logical_insert.rs:157-161 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:357-361 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 4 call sites, so a change lands once.
DatabaseCheckpointControl::apply_command (cyclomatic 79) src/meta/src/barrier/checkpoint/state.rs:432— DatabaseCheckpointControl::apply_command has cyclomatic complexity 79 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DatabaseCheckpointControl::handle_new_barrier (cyclomatic 18) src/meta/src/barrier/checkpoint/control.rs:1207— DatabaseCheckpointControl::handle_new_barrier has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DatabaseCheckpointControl::next_complete_barrier_task (cyclomatic 17) src/meta/src/barrier/checkpoint/control.rs:989— DatabaseCheckpointControl::next_complete_barrier_task has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HashJoinExecutor::do_execute (cyclomatic 41) src/batch/executors/src/executor/join/hash_join.rs:478— HashJoinExecutor::do_execute has cyclomatic complexity 41 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
HashJoinExecutor::handle_match_rows (cyclomatic 20) src/stream/src/executor/hash_join.rs:1087— HashJoinExecutor::handle_match_rows has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HashJoinExecutor::handle_watermark (cyclomatic 17) src/stream/src/executor/hash_join.rs:815— HashJoinExecutor::handle_watermark has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Decimal::checked_powd (cyclomatic 30) src/common/src/types/decimal.rs:657— Decimal::checked_powd has cyclomatic complexity 30 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Decimal::mul (cyclomatic 24) src/common/src/types/decimal.rs:370— Decimal::mul has cyclomatic complexity 24 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Decimal::div (cyclomatic 20) src/common/src/types/decimal.rs:330— Decimal::div has cyclomatic complexity 20 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Inner::execute (cyclomatic 30) src/stream/src/executor/project/project_set.rs:94— Inner::execute has cyclomatic complexity 30 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Inner::execute (cyclomatic 27) src/stream/src/executor/project/project_scalar.rs:252— Inner::execute has cyclomatic complexity 27 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Inner::execute (cyclomatic 19) src/stream/src/executor/project/materialized_exprs.rs:148— Inner::execute has cyclomatic complexity 19 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
SinkExecutor::process_msg (cyclomatic 26) src/stream/src/executor/sink.rs:590— SinkExecutor::process_msg has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SinkExecutor::execute_consume_log (cyclomatic 20) src/stream/src/executor/sink.rs:743— SinkExecutor::execute_consume_log has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SinkExecutor::execute_write_log (cyclomatic 18) src/stream/src/executor/sink.rs:468— SinkExecutor::execute_write_log has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DatabaseCheckpointControl::apply_command (cognitive 127) src/meta/src/barrier/checkpoint/state.rs:432— DatabaseCheckpointControl::apply_command has cognitive complexity 127 (threshold 15). Drivers by points: if/else 35 (68 pts), loops 19 (47 pts), match/switch 5 (9 pts), boolean chains 3 (nesting depth added 65). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DatabaseCheckpointControl::next_complete_barrier_task (cognitive 31) src/meta/src/barrier/checkpoint/control.rs:989— DatabaseCheckpointControl::next_complete_barrier_task has cognitive complexity 31 (threshold 15). Drivers by points: if/else 11 (24 pts), loops 3 (4 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DatabaseCheckpointControl::handle_new_barrier (cognitive 28) src/meta/src/barrier/checkpoint/control.rs:1207— DatabaseCheckpointControl::handle_new_barrier has cognitive complexity 28 (threshold 15). Drivers by points: if/else 14 (24 pts), boolean chains 3, match/switch 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Inner::execute (cognitive 118) src/stream/src/executor/project/project_set.rs:94— Inner::execute has cognitive complexity 118 (threshold 15). Drivers by points: if/else 11 (48 pts), loops 10 (43 pts), match/switch 5 (24 pts), boolean chains 3 (nesting depth added 89). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Inner::execute (cognitive 81) src/stream/src/executor/project/project_scalar.rs:252— Inner::execute has cognitive complexity 81 (threshold 15). Drivers by points: if/else 16 (53 pts), match/switch 5 (17 pts), loops 3 (10 pts), boolean chains 1 (nesting depth added 56). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Inner::execute (cognitive 60) src/stream/src/executor/project/materialized_exprs.rs:148— Inner::execute has cognitive complexity 60 (threshold 15). Drivers by points: loops 8 (32 pts), if/else 5 (16 pts), match/switch 3 (10 pts), boolean chains 2 (nesting depth added 42). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
AsOfJoinExecutor::eq_join_right (cognitive 96) src/stream/src/executor/asof_join.rs:764— AsOfJoinExecutor::eq_join_right has cognitive complexity 96 (threshold 15). Drivers by points: if/else 24 (66 pts), match/switch 6 (21 pts), loops 2 (5 pts), boolean chains 4 (nesting depth added 60). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
AsOfJoinExecutor::eq_join_left (cognitive 60) src/stream/src/executor/asof_join.rs:574— AsOfJoinExecutor::eq_join_left has cognitive complexity 60 (threshold 15). Drivers by points: if/else 16 (46 pts), match/switch 4 (12 pts), boolean chains 1, loops 1 (nesting depth added 38). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
AsOfJoinExecutor::into_stream (cognitive 21) src/stream/src/executor/asof_join.rs:323— AsOfJoinExecutor::into_stream has cognitive complexity 21 (threshold 15). Drivers by points: loops 6 (16 pts), if/else 1 (3 pts), match/switch 1 (2 pts) (nesting depth added 13). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
SinkExecutor::process_msg (cognitive 83) src/stream/src/executor/sink.rs:590— SinkExecutor::process_msg has cognitive complexity 83 (threshold 15). Drivers by points: if/else 14 (49 pts), loops 6 (24 pts), match/switch 2 (6 pts), boolean chains 4 (nesting depth added 57). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SinkExecutor::execute_consume_log (cognitive 49) src/stream/src/executor/sink.rs:743— SinkExecutor::execute_consume_log has cognitive complexity 49 (threshold 15). Drivers by points: if/else 13 (28 pts), match/switch 4 (13 pts), loops 3 (5 pts), boolean chains 3 (nesting depth added 26). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SinkExecutor::execute_write_log (cognitive 38) src/stream/src/executor/sink.rs:468— SinkExecutor::execute_write_log has cognitive complexity 38 (threshold 15). Drivers by points: if/else 7 (28 pts), match/switch 2 (6 pts), boolean chains 3, loops 1 (nesting depth added 25). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Tokenizer::next_token (cognitive 68) src/sqlparser/src/tokenizer.rs:396— Tokenizer::next_token has cognitive complexity 68 (threshold 15). Drivers by points: if/else 11 (34 pts), match/switch 11 (28 pts), loops 1 (4 pts), boolean chains 2 (nesting depth added 43). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Tokenizer::tokenize_dollar_preceded_value (cognitive 30) src/sqlparser/src/tokenizer.rs:681— Tokenizer::tokenize_dollar_preceded_value has cognitive complexity 30 (threshold 15). Drivers by points: if/else 7 (15 pts), loops 4 (14 pts), boolean chains 1 (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Tokenizer::unescape_c_style (cognitive 27) src/sqlparser/src/tokenizer.rs:869— Tokenizer::unescape_c_style has cognitive complexity 27 (threshold 15). Drivers by points: if/else 10 (13 pts), match/switch 2 (7 pts), boolean chains 4, loops 3 (nesting depth added 8). Most of this is not in the body itself: 11 of the 27 points are its own statements and the rest belongs to 2 function items inside it that branch (hex_byte_process, octal_byte_process). Those helpers are already separate functions, so extracting the branching again is not available. To reduce it, move them out of the body to the enclosing scope, where each is measured, reviewed and tested on its own, and reduce whichever one then reads as the largest.
HummockVersionCommon::build_sst_delta_infos (cognitive 68) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:390— HummockVersionCommon::build_sst_delta_infos has cognitive complexity 68 (threshold 15). Drivers by points: if/else 13 (43 pts), loops 7 (21 pts), match/switch 1 (3 pts), boolean chains 1 (nesting depth added 46). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockVersionCommon::apply_version_delta (cognitive 61) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:499— HummockVersionCommon::apply_version_delta has cognitive complexity 61 (threshold 15). Drivers by points: if/else 20 (48 pts), loops 6 (7 pts), boolean chains 3, match/switch 1 (3 pts) (nesting depth added 31). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockVersionCommon::init_with_parent_group_v2 (cognitive 22) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:855— HummockVersionCommon::init_with_parent_group_v2 has cognitive complexity 22 (threshold 15). Drivers by points: if/else 11 (18 pts), loops 2, match/switch 1 (2 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashAggExecutor::do_execute (cognitive 61) src/batch/executors/src/executor/hash_agg.rs:495— HashAggExecutor::do_execute has cognitive complexity 61 (threshold 15). Drivers by points: loops 14 (36 pts), if/else 9 (19 pts), match/switch 2 (4 pts), boolean chains 2 (nesting depth added 34). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
HashAggExecutor::execute_inner (cognitive 50) src/stream/src/executor/aggregate/hash_agg.rs:561— HashAggExecutor::execute_inner has cognitive complexity 50 (threshold 15). Drivers by points: if/else 10 (34 pts), loops 6 (14 pts), match/switch 1 (2 pts) (nesting depth added 33). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HashAggExecutor::flush_data (cognitive 27) src/stream/src/executor/aggregate/hash_agg.rs:412— HashAggExecutor::flush_data has cognitive complexity 27 (threshold 15). Drivers by points: if/else 10 (18 pts), loops 4 (7 pts), boolean chains 2 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
OverPartition::build_changes (cognitive 49) src/stream/src/executor/over_window/over_partition.rs:150— OverPartition::build_changes has cognitive complexity 49 (threshold 15). Drivers by points: if/else 13 (38 pts), loops 5 (9 pts), boolean chains 2 (nesting depth added 29). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
OverPartition::find_affected_ranges_readonly (cognitive 36) src/stream/src/executor/over_window/over_partition.rs:600— OverPartition::find_affected_ranges_readonly has cognitive complexity 36 (threshold 15). Drivers by points: if/else 22 (28 pts), boolean chains 6, loops 2 (nesting depth added 6). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
OverPartition::clean_stale_rows (cognitive 28) src/stream/src/executor/over_window/over_partition.rs:364— OverPartition::clean_stale_rows has cognitive complexity 28 (threshold 15). Drivers by points: if/else 15 (22 pts), loops 2 (3 pts), boolean chains 2, match/switch 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Planner::plan_select (cognitive 46) src/frontend/src/planner/select.rs:45— Planner::plan_select has cognitive complexity 46 (threshold 15). Drivers by points: if/else 21 (32 pts), loops 3 (6 pts), boolean chains 4, match/switch 2 (4 pts) (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Planner::plan_iceberg_table (cognitive 37) src/frontend/src/planner/relation.rs:133— Planner::plan_iceberg_table has cognitive complexity 37 (threshold 15). Drivers by points: if/else 20 (26 pts), match/switch 4 (6 pts), boolean chains 4, loops 1 (nesting depth added 8). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
Planner::plan_source (cognitive 24) src/frontend/src/planner/relation.rs:350— Planner::plan_source has cognitive complexity 24 (threshold 15). Drivers by points: if/else 11 (20 pts), boolean chains 2, match/switch 1 (2 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceManagerCore::reassign_splits (cognitive 44) src/meta/src/stream/source_manager/split_assignment.rs:344— SourceManagerCore::reassign_splits has cognitive complexity 44 (threshold 15). Drivers by points: if/else 7 (25 pts), match/switch 4 (12 pts), loops 4 (7 pts) (nesting depth added 29). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceManagerCore::drop_source_fragments (cognitive 31) src/meta/src/stream/source_manager.rs:280— SourceManagerCore::drop_source_fragments has cognitive complexity 31 (threshold 15). Drivers by points: if/else 10 (23 pts), loops 3 (8 pts) (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceManagerCore::apply_source_change (cognitive 26) src/meta/src/stream/source_manager.rs:148— SourceManagerCore::apply_source_change has cognitive complexity 26 (threshold 15). Drivers by points: loops 10 (14 pts), if/else 5 (11 pts), match/switch 1 (nesting depth added 10). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_common_proc_macro::derive_estimate_size (cognitive 38) src/common/proc_macro/src/lib.rs:71— risingwave_common_proc_macro::derive_estimate_size has cognitive complexity 38 (threshold 15). Drivers by points: loops 6 (20 pts), if/else 4 (12 pts), match/switch 3 (6 pts) (nesting depth added 25). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_common_proc_macro::session_config::derive_config (cognitive 37) src/common/proc_macro/src/session_config.rs:31— risingwave_common_proc_macro::session_config::derive_config has cognitive complexity 37 (threshold 15). Drivers by points: if/else 17 (32 pts), loops 2 (3 pts), boolean chains 2 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_common_proc_macro::estimate_size::extract_ignored_generics (cognitive 36) src/common/proc_macro/src/estimate_size.rs:86— risingwave_common_proc_macro::estimate_size::extract_ignored_generics has cognitive complexity 36 (threshold 15). Drivers by points: if/else 7 (26 pts), loops 2 (9 pts), boolean chains 1 (nesting depth added 26). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
LogicalMultiJoin::as_bushy_tree_join (cognitive 37) src/frontend/src/optimizer/plan_node/logical_multi_join.rs:512— LogicalMultiJoin::as_bushy_tree_join has cognitive complexity 37 (threshold 15). Drivers by points: if/else 12 (26 pts), loops 3 (6 pts), match/switch 2 (4 pts), boolean chains 1 (nesting depth added 19). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalMultiJoin::heuristic_ordering (cognitive 28) src/frontend/src/optimizer/plan_node/logical_multi_join.rs:423— LogicalMultiJoin::heuristic_ordering has cognitive complexity 28 (threshold 15). Drivers by points: if/else 8 (19 pts), loops 5 (8 pts), boolean chains 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalMultiJoin::eq_condition_derivation (cognitive 22) src/frontend/src/optimizer/plan_node/logical_multi_join.rs:703— LogicalMultiJoin::eq_condition_derivation has cognitive complexity 22 (threshold 15). Drivers by points: if/else 4 (12 pts), loops 6 (10 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DdlController::replace_job (cognitive 34) src/meta/src/rpc/ddl_controller.rs:1608— DdlController::replace_job has cognitive complexity 34 (threshold 15). Drivers by points: if/else 12 (24 pts), loops 3 (7 pts), match/switch 2, boolean chains 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DdlController::create_streaming_job (cognitive 33) src/meta/src/rpc/ddl_controller.rs:1131— DdlController::create_streaming_job has cognitive complexity 33 (threshold 15). Drivers by points: if/else 16 (28 pts), match/switch 4, boolean chains 1 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DdlController::build_replace_job (cognitive 16) src/meta/src/rpc/ddl_controller.rs:2157— DdlController::build_replace_job has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (10 pts), loops 2 (4 pts), match/switch 2 (nesting depth added 4). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
LocalBarrierWorker::run (cognitive 34) src/stream/src/task/barrier_worker/mod.rs:370— LocalBarrierWorker::run has cognitive complexity 34 (threshold 15). Drivers by points: match/switch 5 (17 pts), if/else 4 (12 pts), loops 2 (5 pts) (nesting depth added 23). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
LocalBarrierWorker::handle_actor_op (cognitive 20) src/stream/src/task/barrier_worker/mod.rs:508— LocalBarrierWorker::handle_actor_op has cognitive complexity 20 (threshold 15). Drivers by points: match/switch 4 (9 pts), if/else 3 (7 pts), loops 2 (4 pts) (nesting depth added 11). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
LocalBarrierWorker::add_partial_graph (cognitive 17) src/stream/src/task/barrier_worker/mod.rs:933— LocalBarrierWorker::add_partial_graph has cognitive complexity 17 (threshold 15). Drivers by points: if/else 5 (13 pts), loops 1 (3 pts), match/switch 1 (nesting depth added 10). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
GlobalStreamManager::run (cognitive 33) src/meta/src/stream/scale.rs:1412— GlobalStreamManager::run has cognitive complexity 33 (threshold 15). Drivers by points: match/switch 5 (16 pts), if/else 4 (15 pts), boolean chains 1, loops 1 (nesting depth added 22). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
GlobalStreamManager::create_streaming_job (cognitive 17) src/meta/src/stream/stream_manager.rs:377— GlobalStreamManager::create_streaming_job has cognitive complexity 17 (threshold 15). Drivers by points: if/else 5 (8 pts), match/switch 4 (7 pts), loops 1 (2 pts) (nesting depth added 7). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
GlobalStreamManager::run_create_streaming_job_command (cognitive 16) src/meta/src/stream/stream_manager.rs:596— GlobalStreamManager::run_create_streaming_job_command has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (13 pts), loops 1 (2 pts), boolean chains 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MonitorServiceImpl::get_streaming_stats (cognitive 30) src/compute/src/rpc/service/monitor_service.rs:267— MonitorServiceImpl::get_streaming_stats has cognitive complexity 30 (threshold 15). Drivers by points: if/else 11 (19 pts), loops 7 (8 pts), match/switch 1 (3 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MonitorServiceImpl::tiered_cache_tracing (cognitive 18) src/compute/src/rpc/service/monitor_service.rs:413— MonitorServiceImpl::tiered_cache_tracing has cognitive complexity 18 (threshold 15). Drivers by points: if/else 14 (18 pts) (nesting depth added 4). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
MonitorServiceImpl::stack_trace (cognitive 17) src/compute/src/rpc/service/monitor_service.rs:86— MonitorServiceImpl::stack_trace has cognitive complexity 17 (threshold 15). Drivers by points: if/else 13 (14 pts), match/switch 2, boolean chains 1 (nesting depth added 1). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
SubscriptionCursor::next_row (cognitive 24) src/frontend/src/session/cursor_manager.rs:500— SubscriptionCursor::next_row has cognitive complexity 24 (threshold 15). Drivers by points: if/else 7 (18 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SubscriptionCursor::next (cognitive 24) src/frontend/src/session/cursor_manager.rs:633— SubscriptionCursor::next has cognitive complexity 24 (threshold 15). Drivers by points: if/else 8 (16 pts), match/switch 2 (5 pts), boolean chains 2, loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SubscriptionCursor::create_batch_plan_for_cursor (cognitive 24) src/frontend/src/session/cursor_manager.rs:924— SubscriptionCursor::create_batch_plan_for_cursor has cognitive complexity 24 (threshold 15). Drivers by points: if/else 12 (17 pts), match/switch 2 (3 pts), boolean chains 2, loops 1 (2 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TopNCache::delete (cognitive 24) src/stream/src/executor/top_n/top_n_cache.rs:373— TopNCache::delete has cognitive complexity 24 (threshold 15). Drivers by points: if/else 12 (21 pts), boolean chains 3 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TopNCache::insert (cognitive 22) src/stream/src/executor/top_n/top_n_cache.rs:486— TopNCache::insert has cognitive complexity 22 (threshold 15). Drivers by points: if/else 8 (17 pts), loops 1 (3 pts), boolean chains 1, match/switch 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TopNCache::insert (cognitive 19) src/stream/src/executor/top_n/top_n_cache.rs:294— TopNCache::insert has cognitive complexity 19 (threshold 15). Drivers by points: if/else 10 (16 pts), boolean chains 3 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StateTableRowStore::seal_current_epoch (cognitive 22) src/stream/src/common/table/state_table.rs:514— StateTableRowStore::seal_current_epoch has cognitive complexity 22 (threshold 15). Drivers by points: loops 3 (13 pts), match/switch 3 (7 pts), boolean chains 1, if/else 1 (nesting depth added 14). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
StateTableRowStore::iter_kv (cognitive 18) src/stream/src/common/table/state_table.rs:1950— StateTableRowStore::iter_kv has cognitive complexity 18 (threshold 15). Drivers by points: if/else 9 (13 pts), boolean chains 3, match/switch 1 (2 pts) (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body. This shape REPEATS in the file: one other method here (StateTableRowStore::rev_iter_kv) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
StateTableRowStore::rev_iter_kv (cognitive 18) src/stream/src/common/table/state_table.rs:2038— StateTableRowStore::rev_iter_kv has cognitive complexity 18 (threshold 15). Drivers by points: if/else 9 (13 pts), boolean chains 3, match/switch 1 (2 pts) (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body. This shape REPEATS in the file: one other method here (StateTableRowStore::iter_kv) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
IndexSelectionRule::gen_paths (cognitive 18) src/frontend/src/optimizer/rule/index_selection_rule.rs:379— IndexSelectionRule::gen_paths has cognitive complexity 18 (threshold 15). Drivers by points: if/else 6 (10 pts), loops 2 (3 pts), match/switch 1 (3 pts), boolean chains 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IndexSelectionRule::gen_index_path (cognitive 18) src/frontend/src/optimizer/rule/index_selection_rule.rs:537— IndexSelectionRule::gen_index_path has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 2 (3 pts), match/switch 1 (3 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IndexSelectionRule::apply (cognitive 16) src/frontend/src/optimizer/rule/index_selection_rule.rs:93— IndexSelectionRule::apply has cognitive complexity 16 (threshold 15). Drivers by points: if/else 9 (14 pts), boolean chains 1, loops 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Duplicated block (27 lines × 2) src/jni_core/src/lib.rs:706— src/jni_core/src/lib.rs:706-739 | src/jni_core/src/lib.rs:934-960 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (27 lines × 2) src/stream/src/executor/backfill/cdc/upstream_table/snapshot.rs:229— src/stream/src/executor/backfill/cdc/upstream_table/snapshot.rs:229-255 | src/stream/src/executor/backfill/cdc/upstream_table/snapshot.rs:313-339 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (27 lines × 2) src/stream/src/executor/gap_fill.rs:648— src/stream/src/executor/gap_fill.rs:648-674 | src/stream/src/executor/gap_fill.rs:725-751 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (21–24 lines × 2) src/batch/executors/src/executor/hop_window.rs:146— src/batch/executors/src/executor/hop_window.rs:146-166 | src/stream/src/executor/hop_window.rs:77-100 — before extracting anything, compare `src/batch/executors/src/executor/hop_window.rs` and `src/stream/src/executor/hop_window.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (21–24 lines × 2) src/frontend/src/optimizer/plan_node/logical_join.rs:443— src/frontend/src/optimizer/plan_node/logical_join.rs:443-463 | src/frontend/src/optimizer/plan_node/logical_join.rs:1214-1237 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (21–24 lines × 2) src/stream/src/executor/asof_join.rs:601— src/stream/src/executor/asof_join.rs:601-621 | src/stream/src/executor/asof_join.rs:787-810 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20–21 lines × 2) src/batch/executors/src/executor/hash_agg.rs:333— src/batch/executors/src/executor/hash_agg.rs:333-353 | src/batch/executors/src/executor/join/hash_join.rs:287-306 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/join/hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 81 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (20–21 lines × 2) src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/stream.rs:313— src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/stream.rs:313-332 | src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/stream.rs:356-376 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20–21 lines × 2) src/stream/src/from_proto/asof_join.rs:48— src/stream/src/from_proto/asof_join.rs:48-68 | src/stream/src/from_proto/hash_join.rs:56-75 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (21 lines × 2) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:223— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:223-243 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:308-328 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (21 lines × 2) src/sqlparser/src/parser.rs:661— src/sqlparser/src/parser.rs:661-681 | src/sqlparser/src/parser.rs:1416-1436 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (21 lines × 2) src/stream/src/common/table/state_table.rs:1957— src/stream/src/common/table/state_table.rs:1957-1977 | src/stream/src/common/table/state_table.rs:2045-2065 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15–17 lines × 2) src/meta/src/barrier/rpc.rs:132— src/meta/src/barrier/rpc.rs:132-146 | src/meta/src/stream/stream_graph/fragment.rs:1463-1479 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (15–17 lines × 2) src/stream/src/executor/mview/cache.rs:198— src/stream/src/executor/mview/cache.rs:198-214 | src/stream/src/executor/mview/cache.rs:254-268 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15–17 lines × 2) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java:88— java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java:88-104 | java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/JDBCSink.java:89-103 — before extracting anything, compare `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/BatchAppendOnlyJDBCSink.java` and `java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/JDBCSink.java` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 97 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names — the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately.
Duplicated block (14–16 lines × 2) src/storage/src/memory.rs:177— src/storage/src/memory.rs:177-190 | src/storage/src/memory.rs:212-227 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–16 lines × 2) src/stream/src/executor/backfill/cdc/cdc_backfill.rs:382— src/stream/src/executor/backfill/cdc/cdc_backfill.rs:382-397 | src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:151-164 — before extracting anything, compare `src/stream/src/executor/backfill/cdc/cdc_backfill.rs` and `src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 38 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (14–16 lines × 2) e2e_test/check_slt_coverage.py:566— e2e_test/check_slt_coverage.py:566-579 | e2e_test/check_slt_coverage.py:581-596 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at `e2e_test/check_slt_coverage.py:566` it does not close everything it opens, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (9–11 lines × 2) src/common/src/util/scan_range.rs:176— src/common/src/util/scan_range.rs:176-184 | src/common/src/util/scan_range.rs:214-224 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9–11 lines × 2) src/frontend/src/optimizer/plan_node/generic/join.rs:257— src/frontend/src/optimizer/plan_node/generic/join.rs:257-265 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:389-399 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/generic/join.rs` and `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 30 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (9–11 lines × 2) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/DbzChangeEventConsumer.java:220— java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/DbzChangeEventConsumer.java:220-230 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/DbzChangeEventConsumer.java:274-282 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8–9 lines × 2) src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:115— src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:115-122 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_files.rs:107-115 — before extracting anything, compare `src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs` and `src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_files.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 41 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (8–9 lines × 2) src/frontend/src/handler/alter_rename.rs:173— src/frontend/src/handler/alter_rename.rs:173-181 | src/frontend/src/handler/alter_subscription_retention.rs:92-99 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (8–9 lines × 2) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:205— java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:205-212 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java:143-151 — before extracting anything, compare `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java` and `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 34 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:205` it does not close everything it opens, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (5 lines × 6) src/connector/src/source/cdc/source/reader.rs:216— src/connector/src/source/cdc/source/reader.rs:216-220 | src/connector/src/source/google_pubsub/source/reader.rs:156-160 | src/connector/src/source/kinesis/source/reader.rs:168-172 | src/connector/src/source/mqtt/source/reader.rs:83-87 | src/connector/src/source/nats/source/reader.rs:116-120 | src/connector/src/source/pulsar/source/reader.rs:296-300 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 6 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 6 times.
Duplicated block (5 lines × 6) src/meta/src/controller/utils.rs:941— src/meta/src/controller/utils.rs:941-948 | src/meta/src/controller/utils.rs:960-964 | src/meta/src/controller/utils.rs:976-980 | src/meta/src/controller/utils.rs:992-1000 | src/meta/src/controller/utils.rs:1013-1017 | src/meta/src/controller/utils.rs:1029-1033 — all 6 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 6) REDACTED:321— REDACTED:321-325 | REDACTED:329-333 | REDACTED:352-356 | REDACTED:416-420 | REDACTED:425-429 | REDACTED:434-438 — all 6 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just before the matched lines, `REDACTED:423` calls `execute_insert` and `REDACTED:328` does not — after which the two agree again for 3 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
AC2 · Forms & labels· <Select> field component without a label · ×2
<Select> field component without a label dashboard/pages/await_tree.tsx:120— This UI-library field component has no label / aria-label / aria-labelledby / id / name, and nothing it renders carries one either. The text inside it does not stand in for one: these compound APIs render a trigger with role="combobox" (or role="button"), and those roles take their name from the AUTHOR, not from their content — so the words on screen never reach the accessibility tree as a name. Name it whichever way this library supports: a label prop, an aria-label, or an id on the rendered control with a <label htmlFor> pointing at it. For a group of controls, name the group itself (aria-label, or a fieldset with a legend) — labelling each item leaves the set unnamed.
<Select> field component without a label dashboard/pages/fragment_graph.tsx:411— This UI-library field component has no label / aria-label / aria-labelledby / id / name, and nothing it renders carries one either. The text inside it does not stand in for one: these compound APIs render a trigger with role="combobox" (or role="button"), and those roles take their name from the AUTHOR, not from their content — so the words on screen never reach the accessibility tree as a name. Name it whichever way this library supports: a label prop, an aria-label, or an id on the rendered control with a <label htmlFor> pointing at it. For a group of controls, name the group itself (aria-label, or a fieldset with a legend) — labelling each item leaves the set unnamed.
Tokenizer::next_token (cyclomatic 66) src/sqlparser/src/tokenizer.rs:396— Tokenizer::next_token has cyclomatic complexity 66 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Tokenizer::unescape_c_style (cyclomatic 24) src/sqlparser/src/tokenizer.rs:869— Tokenizer::unescape_c_style has cyclomatic complexity 24 (threshold 15). Of this number, 13 points are the body's own statements and 11 belong to 2 function items inside it that branch. To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions. This is NOT this file's highest cyclomatic complexity: Token::fmt (cyclomatic 38) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
GlobalBarrierWorker::run_inner (cyclomatic 52) src/meta/src/barrier/worker.rs:516— GlobalBarrierWorker::run_inner has cyclomatic complexity 52 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
GlobalBarrierWorker::recovery_inner (cyclomatic 33) src/meta/src/barrier/worker.rs:1140— GlobalBarrierWorker::recovery_inner has cyclomatic complexity 33 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
TestCase::apply_query (cyclomatic 39) src/frontend/planner_test/src/lib.rs:611— TestCase::apply_query has cyclomatic complexity 39 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
TestCase::run_sql (cyclomatic 18) src/frontend/planner_test/src/lib.rs:397— TestCase::run_sql has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_backup::meta_snapshot_v2::encode_metadata_to_writer (cyclomatic 38) src/storage/backup/src/meta_snapshot_v2.rs:102— risingwave_backup::meta_snapshot_v2::encode_metadata_to_writer has cyclomatic complexity 38 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_backup::meta_snapshot_v2::decode_metadata_from_reader) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
risingwave_backup::meta_snapshot_v2::decode_metadata_from_reader (cyclomatic 38) src/storage/backup/src/meta_snapshot_v2.rs:123— risingwave_backup::meta_snapshot_v2::decode_metadata_from_reader has cyclomatic complexity 38 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_backup::meta_snapshot_v2::encode_metadata_to_writer) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
risedev::bin::risedev-dev::task_main (cyclomatic 35) src/risedevtool/src/bin/risedev-dev.rs:66— risedev::bin::risedev-dev::task_main has cyclomatic complexity 35 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risedev::risedev_env::generate_risedev_env (cyclomatic 28) src/risedevtool/src/risedev_env.rs:25— risedev::risedev_env::generate_risedev_env has cyclomatic complexity 28 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector_codec::decoder::avro::schema::avro_type_mapping (cyclomatic 34) src/connector/codec/src/decoder/avro/schema.rs:101— risingwave_connector_codec::decoder::avro::schema::avro_type_mapping has cyclomatic complexity 34 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risingwave_connector_codec::decoder::protobuf::parser::from_protobuf_value (cyclomatic 22) src/connector/codec/src/decoder/protobuf/parser.rs:106— risingwave_connector_codec::decoder::protobuf::parser::from_protobuf_value has cyclomatic complexity 22 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
AsOfJoinExecutor::eq_join_right (cyclomatic 34) src/stream/src/executor/asof_join.rs:764— AsOfJoinExecutor::eq_join_right has cyclomatic complexity 34 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
AsOfJoinExecutor::eq_join_left (cyclomatic 24) src/stream/src/executor/asof_join.rs:574— AsOfJoinExecutor::eq_join_left has cyclomatic complexity 24 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Planner::plan_select (cyclomatic 28) src/frontend/src/planner/select.rs:45— Planner::plan_select has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Planner::plan_iceberg_table (cyclomatic 27) src/frontend/src/planner/relation.rs:133— Planner::plan_iceberg_table has cyclomatic complexity 27 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
HummockVersionCommon::apply_version_delta (cyclomatic 28) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:499— HummockVersionCommon::apply_version_delta has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HummockVersionCommon::build_sst_delta_infos (cyclomatic 23) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:390— HummockVersionCommon::build_sst_delta_infos has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
PgProtocol::do_process_inner (cyclomatic 27) src/utils/pgwire/src/pg_protocol.rs:580— PgProtocol::do_process_inner has cyclomatic complexity 27 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
PgProtocol::do_process (cyclomatic 16) src/utils/pgwire/src/pg_protocol.rs:400— PgProtocol::do_process has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HashAggExecutor::do_execute (cyclomatic 26) src/batch/executors/src/executor/hash_agg.rs:495— HashAggExecutor::do_execute has cyclomatic complexity 26 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
HashAggExecutor::execute_inner (cyclomatic 18) src/stream/src/executor/aggregate/hash_agg.rs:561— HashAggExecutor::execute_inner has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
GapFillExecutor::generate_filled_rows_between_static (cyclomatic 26) src/stream/src/executor/gap_fill.rs:268— GapFillExecutor::generate_filled_rows_between_static has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
GapFillExecutor::execute_inner (cyclomatic 26) src/stream/src/executor/gap_fill.rs:536— GapFillExecutor::execute_inner has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
OverPartition::find_affected_ranges_readonly (cyclomatic 26) src/stream/src/executor/over_window/over_partition.rs:600— OverPartition::find_affected_ranges_readonly has cyclomatic complexity 26 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
OverPartition::build_changes (cyclomatic 19) src/stream/src/executor/over_window/over_partition.rs:150— OverPartition::build_changes has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DynamicFilterExecutor::execute_inner (cyclomatic 23) src/stream/src/executor/dynamic_filter.rs:265— DynamicFilterExecutor::execute_inner has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DynamicFilterExecutor::apply_batch (cyclomatic 17) src/stream/src/executor/dynamic_filter.rs:89— DynamicFilterExecutor::apply_batch has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ScalarAdapter::into_scalar (cyclomatic 22) src/connector/src/parser/scalar_adapter.rs:302— ScalarAdapter::into_scalar has cyclomatic complexity 22 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
ScalarAdapter::from_scalar (cyclomatic 18) src/connector/src/parser/scalar_adapter.rs:223— ScalarAdapter::from_scalar has cyclomatic complexity 18 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
MatchRecognizeExecutor::execute_inner (cyclomatic 22) src/stream/src/executor/match_recognize/executor.rs:1168— MatchRecognizeExecutor::execute_inner has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
MatchRecognizeExecutor::emit_ready (cyclomatic 16) src/stream/src/executor/match_recognize/executor.rs:731— MatchRecognizeExecutor::emit_ready has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HummockVersionReader::get (cyclomatic 21) src/storage/src/hummock/store/version.rs:635— HummockVersionReader::get has cyclomatic complexity 21 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HummockVersionReader::iter_inner (cyclomatic 21) src/storage/src/hummock/store/version.rs:988— HummockVersionReader::iter_inner has cyclomatic complexity 21 (threshold 15). Of this number, 20 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DdlServiceImpl::auto_schema_change (cyclomatic 20) src/meta/service/src/ddl_service.rs:1340— DdlServiceImpl::auto_schema_change has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DdlServiceImpl::create_iceberg_table (cyclomatic 16) src/meta/service/src/ddl_service.rs:1789— DdlServiceImpl::create_iceberg_table has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SourceManagerCore::apply_source_change (cyclomatic 20) src/meta/src/stream/source_manager.rs:148— SourceManagerCore::apply_source_change has cyclomatic complexity 20 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
SourceManagerCore::reassign_splits (cyclomatic 16) src/meta/src/stream/source_manager/split_assignment.rs:344— SourceManagerCore::reassign_splits has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DdlController::create_streaming_job (cyclomatic 18) src/meta/src/rpc/ddl_controller.rs:1131— DdlController::create_streaming_job has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: DdlController::run_command (cyclomatic 32) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
DdlController::replace_job (cyclomatic 17) src/meta/src/rpc/ddl_controller.rs:1608— DdlController::replace_job has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: DdlController::run_command (cyclomatic 32) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
risingwave_common_proc_macro::session_config::derive_config (cyclomatic 17) src/common/proc_macro/src/session_config.rs:31— risingwave_common_proc_macro::session_config::derive_config has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_common_proc_macro::derive_estimate_size (cyclomatic 17) src/common/proc_macro/src/lib.rs:71— risingwave_common_proc_macro::derive_estimate_size has cyclomatic complexity 17 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
ApplyJoinTransposeRule::apply (cyclomatic 17) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:89— ApplyJoinTransposeRule::apply has cyclomatic complexity 17 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
ApplyJoinTransposeRule::push_apply_both_side (cyclomatic 16) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:420— ApplyJoinTransposeRule::push_apply_both_side has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
LocalBarrierWorker::run (cyclomatic 17) src/stream/src/task/barrier_worker/mod.rs:370— LocalBarrierWorker::run has cyclomatic complexity 17 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
LocalBarrierWorker::handle_actor_op (cyclomatic 16) src/stream/src/task/barrier_worker/mod.rs:508— LocalBarrierWorker::handle_actor_op has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
CdcBackfillExecutor::execute_inner (cognitive 195) src/stream/src/executor/backfill/cdc/cdc_backfill.rs:329— CdcBackfillExecutor::execute_inner has cognitive complexity 195 (threshold 15). Drivers by points: if/else 33 (116 pts), match/switch 9 (38 pts), loops 10 (34 pts), boolean chains 7 (nesting depth added 136). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
CdcBackfillExecutor::consume_upstream_chunk_buffer (cognitive 27) src/stream/src/executor/backfill/cdc/cdc_backfill.rs:204— CdcBackfillExecutor::consume_upstream_chunk_buffer has cognitive complexity 27 (threshold 15). Drivers by points: if/else 8 (21 pts), loops 2 (3 pts), match/switch 1 (3 pts) (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MaterializeExecutor::execute_inner (cognitive 182) src/stream/src/executor/mview/materialize.rs:373— MaterializeExecutor::execute_inner has cognitive complexity 182 (threshold 15). Drivers by points: if/else 32 (117 pts), match/switch 10 (44 pts), loops 5 (13 pts), boolean chains 8 (nesting depth added 127). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MaterializeExecutor::make_mergesort_stream (cognitive 28) src/stream/src/executor/mview/materialize.rs:894— MaterializeExecutor::make_mergesort_stream has cognitive complexity 28 (threshold 15). Drivers by points: if/else 8 (18 pts), loops 3 (6 pts), match/switch 1 (4 pts) (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceBackfillExecutorInner::execute (cognitive 165) src/stream/src/executor/source/source_backfill_executor.rs:383— SourceBackfillExecutorInner::execute has cognitive complexity 165 (threshold 15). Drivers by points: if/else 33 (126 pts), match/switch 7 (21 pts), loops 7 (15 pts), boolean chains 3 (nesting depth added 115). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceBackfillExecutorInner::update_state_if_changed_forward_stage (cognitive 16) src/stream/src/executor/source/source_backfill_executor.rs:1131— SourceBackfillExecutorInner::update_state_if_changed_forward_stage has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (7 pts), match/switch 2 (7 pts), loops 2 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceExecutor::execute_inner (cognitive 148) src/stream/src/executor/source/source_executor.rs:616— SourceExecutor::execute_inner has cognitive complexity 148 (threshold 15). Drivers by points: if/else 36 (120 pts), match/switch 4 (15 pts), loops 3 (9 pts), boolean chains 4 (nesting depth added 101). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceExecutor::persist_state_and_clear_cache (cognitive 22) src/stream/src/executor/source/source_executor.rs:485— SourceExecutor::persist_state_and_clear_cache has cognitive complexity 22 (threshold 15). Drivers by points: if/else 5 (17 pts), match/switch 1 (3 pts), loops 1 (2 pts) (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
GlobalBarrierWorker::run_inner (cognitive 138) src/meta/src/barrier/worker.rs:516— GlobalBarrierWorker::run_inner has cognitive complexity 138 (threshold 15). Drivers by points: if/else 27 (99 pts), match/switch 10 (33 pts), loops 2 (6 pts) (nesting depth added 99). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
GlobalBarrierWorker::recovery_inner (cognitive 53) src/meta/src/barrier/worker.rs:1140— GlobalBarrierWorker::recovery_inner has cognitive complexity 53 (threshold 15). Drivers by points: if/else 15 (31 pts), match/switch 5 (12 pts), loops 6 (8 pts), boolean chains 2 (nesting depth added 25). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
GapFillExecutor::execute_inner (cognitive 91) src/stream/src/executor/gap_fill.rs:536— GapFillExecutor::execute_inner has cognitive complexity 91 (threshold 15). Drivers by points: if/else 16 (67 pts), loops 4 (14 pts), match/switch 2 (6 pts), boolean chains 4 (nesting depth added 65). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
GapFillExecutor::generate_filled_rows_between_static (cognitive 47) src/stream/src/executor/gap_fill.rs:268— GapFillExecutor::generate_filled_rows_between_static has cognitive complexity 47 (threshold 15). Drivers by points: if/else 17 (27 pts), match/switch 6 (15 pts), loops 4 (5 pts) (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
OverWindowExecutor::apply_chunk (cognitive 79) src/stream/src/executor/over_window/general.rs:374— OverWindowExecutor::apply_chunk has cognitive complexity 79 (threshold 15). Drivers by points: if/else 24 (61 pts), match/switch 3 (10 pts), loops 4 (6 pts), boolean chains 2 (nesting depth added 46). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
OverWindowExecutor::executor_inner (cognitive 29) src/stream/src/executor/over_window/general.rs:689— OverWindowExecutor::executor_inner has cognitive complexity 29 (threshold 15). Drivers by points: if/else 5 (17 pts), loops 3 (8 pts), boolean chains 2, match/switch 1 (2 pts) (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
FsFetchExecutor::into_stream (cognitive 74) src/stream/src/executor/source/fs_fetch_executor.rs:294— FsFetchExecutor::into_stream has cognitive complexity 74 (threshold 15). Drivers by points: if/else 13 (47 pts), match/switch 6 (25 pts), boolean chains 1, loops 1 (nesting depth added 53). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
FsFetchExecutor::replace_with_new_batch_reader (cognitive 20) src/stream/src/executor/source/fs_fetch_executor.rs:145— FsFetchExecutor::replace_with_new_batch_reader has cognitive complexity 20 (threshold 15). Drivers by points: if/else 4 (8 pts), match/switch 2 (7 pts), loops 3 (5 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StreamSink::create (cognitive 73) src/frontend/src/optimizer/plan_node/stream_sink.rs:280— StreamSink::create has cognitive complexity 73 (threshold 15). Drivers by points: if/else 34 (51 pts), boolean chains 18, match/switch 3 (4 pts) (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StreamSink::derive_sink_type (cognitive 19) src/frontend/src/optimizer/plan_node/stream_sink.rs:742— StreamSink::derive_sink_type has cognitive complexity 19 (threshold 15). Drivers by points: if/else 5 (11 pts), match/switch 4 (7 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DynamicFilterExecutor::execute_inner (cognitive 69) src/stream/src/executor/dynamic_filter.rs:265— DynamicFilterExecutor::execute_inner has cognitive complexity 69 (threshold 15). Drivers by points: if/else 15 (55 pts), loops 3 (8 pts), match/switch 2 (6 pts) (nesting depth added 49). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DynamicFilterExecutor::apply_batch (cognitive 35) src/stream/src/executor/dynamic_filter.rs:89— DynamicFilterExecutor::apply_batch has cognitive complexity 35 (threshold 15). Drivers by points: if/else 16 (26 pts), match/switch 3 (8 pts), loops 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HopWindowExecutor::execute_inner (cognitive 67) src/stream/src/executor/hop_window.rs:72— HopWindowExecutor::execute_inner has cognitive complexity 67 (threshold 15). Drivers by points: if/else 17 (50 pts), loops 4 (11 pts), match/switch 2 (6 pts) (nesting depth added 44). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HopWindowExecutor::do_execute (cognitive 17) src/batch/executors/src/executor/hop_window.rs:144— HopWindowExecutor::do_execute has cognitive complexity 17 (threshold 15). Drivers by points: if/else 8 (14 pts), loops 2 (3 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TestCase::apply_query (cognitive 64) src/frontend/planner_test/src/lib.rs:611— TestCase::apply_query has cognitive complexity 64 (threshold 15). Drivers by points: if/else 19 (31 pts), match/switch 13 (26 pts), boolean chains 6, loops 1 (nesting depth added 25). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TestCase::run_sql (cognitive 21) src/frontend/planner_test/src/lib.rs:397— TestCase::run_sql has cognitive complexity 21 (threshold 15). Drivers by points: if/else 5 (15 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MatchRecognizeExecutor::execute_inner (cognitive 62) src/stream/src/executor/match_recognize/executor.rs:1168— MatchRecognizeExecutor::execute_inner has cognitive complexity 62 (threshold 15). Drivers by points: if/else 11 (40 pts), loops 6 (18 pts), boolean chains 2, match/switch 1 (2 pts) (nesting depth added 42). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MatchRecognizeExecutor::emit_ready (cognitive 28) src/stream/src/executor/match_recognize/executor.rs:731— MatchRecognizeExecutor::emit_ready has cognitive complexity 28 (threshold 15). Drivers by points: if/else 10 (19 pts), loops 3 (6 pts), boolean chains 3 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
KafkaSplitReader::into_data_event_stream (cognitive 58) src/connector/src/source/kafka/source/reader.rs:376— KafkaSplitReader::into_data_event_stream has cognitive complexity 58 (threshold 15). Drivers by points: if/else 14 (38 pts), loops 6 (11 pts), match/switch 3 (7 pts), boolean chains 2 (nesting depth added 33). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
KafkaSplitReader::new (cognitive 16) src/connector/src/source/kafka/source/reader.rs:63— KafkaSplitReader::new has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (12 pts), match/switch 2, boolean chains 1, loops 1 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockVersionReader::get (cognitive 58) src/storage/src/hummock/store/version.rs:635— HummockVersionReader::get has cognitive complexity 58 (threshold 15). Drivers by points: if/else 19 (50 pts), loops 4 (6 pts), match/switch 1 (2 pts) (nesting depth added 34). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockVersionReader::iter_inner (cognitive 41) src/storage/src/hummock/store/version.rs:988— HummockVersionReader::iter_inner has cognitive complexity 41 (threshold 15). Drivers by points: if/else 14 (30 pts), loops 4 (6 pts), boolean chains 4, match/switch 1 (nesting depth added 18). Of this number, 40 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
UploaderData::sync (cognitive 55) src/storage/src/hummock/event_handler/uploader/mod.rs:998— UploaderData::sync has cognitive complexity 55 (threshold 15). Drivers by points: if/else 11 (37 pts), loops 6 (17 pts), boolean chains 1 (nesting depth added 37). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
UploaderData::may_notify_sync_task (cognitive 16) src/storage/src/hummock/event_handler/uploader/mod.rs:1597— UploaderData::may_notify_sync_task has cognitive complexity 16 (threshold 15). Drivers by points: if/else 2 (9 pts), loops 3 (6 pts), boolean chains 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CheckpointControl::handle_new_barrier (cognitive 53) src/meta/src/barrier/checkpoint/control.rs:236— CheckpointControl::handle_new_barrier has cognitive complexity 53 (threshold 15). Drivers by points: if/else 13 (38 pts), loops 2 (7 pts), match/switch 3 (7 pts), boolean chains 1 (nesting depth added 34). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
CheckpointControl::next_event (cognitive 24) src/meta/src/barrier/checkpoint/control.rs:626— CheckpointControl::next_event has cognitive complexity 24 (threshold 15). Drivers by points: if/else 4 (12 pts), match/switch 2 (6 pts), loops 2 (5 pts), boolean chains 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DdlServiceImpl::auto_schema_change (cognitive 44) src/meta/service/src/ddl_service.rs:1340— DdlServiceImpl::auto_schema_change has cognitive complexity 44 (threshold 15). Drivers by points: if/else 10 (24 pts), loops 4 (8 pts), match/switch 2 (8 pts), boolean chains 4 (nesting depth added 24). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DdlServiceImpl::create_iceberg_table (cognitive 26) src/meta/service/src/ddl_service.rs:1789— DdlServiceImpl::create_iceberg_table has cognitive complexity 26 (threshold 15). Drivers by points: if/else 11 (19 pts), loops 2 (3 pts), boolean chains 2, match/switch 1 (2 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MaterializeCache::handle_inner (cognitive 42) src/stream/src/executor/mview/cache.rs:153— MaterializeCache::handle_inner has cognitive complexity 42 (threshold 15). Drivers by points: if/else 12 (36 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 27). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MaterializeCache::fetch_keys (cognitive 18) src/stream/src/executor/mview/cache.rs:343— MaterializeCache::fetch_keys has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (12 pts), match/switch 2 (4 pts), loops 2 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ConsumeUpstreamStream::poll_next (cognitive 41) src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/stream.rs:286— ConsumeUpstreamStream::poll_next has cognitive complexity 41 (threshold 15). Drivers by points: loops 5 (17 pts), match/switch 6 (17 pts), if/else 2 (7 pts) (nesting depth added 28). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ConsumeUpstreamStream::new (cognitive 22) src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/stream.rs:467— ConsumeUpstreamStream::new has cognitive complexity 22 (threshold 15). Drivers by points: if/else 7 (10 pts), match/switch 3 (9 pts), loops 2 (3 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DatagenEventGenerator::into_native_stream (cognitive 37) src/connector/src/source/datagen/source/generator.rs:161— DatagenEventGenerator::into_native_stream has cognitive complexity 37 (threshold 15). Drivers by points: if/else 4 (16 pts), match/switch 2 (11 pts), loops 4 (10 pts) (nesting depth added 27). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DatagenEventGenerator::into_msg_stream (cognitive 34) src/connector/src/source/datagen/source/generator.rs:81— DatagenEventGenerator::into_msg_stream has cognitive complexity 34 (threshold 15). Drivers by points: if/else 3 (13 pts), loops 4 (11 pts), match/switch 2 (10 pts) (nesting depth added 25). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_backup::meta_snapshot_v2::encode_metadata_to_writer (cognitive 37) src/storage/backup/src/meta_snapshot_v2.rs:102— risingwave_backup::meta_snapshot_v2::encode_metadata_to_writer has cognitive complexity 37 (threshold 15). Drivers by points: if/else 37. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_backup::meta_snapshot_v2::decode_metadata_from_reader) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
risingwave_backup::meta_snapshot_v2::decode_metadata_from_reader (cognitive 37) src/storage/backup/src/meta_snapshot_v2.rs:123— risingwave_backup::meta_snapshot_v2::decode_metadata_from_reader has cognitive complexity 37 (threshold 15). Drivers by points: if/else 37. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages. This shape REPEATS in the file: one other method here (risingwave_backup::meta_snapshot_v2::encode_metadata_to_writer) has the same decision points, in the same order, at the same nesting depths — so this is one pattern written twice rather than two separate problems. Splitting this body alone leaves the other exactly as it is. Where these are variations on one operation, the change that clears both is the shared one: lift the common shape into a single routine the variants call, parameterised by whatever genuinely differs between them, and keep in each method only the part that is not shared.
LogStoreRowOpStream::next_op (cognitive 37) src/stream/src/common/log_store_impl/kv_log_store/serde.rs:986— LogStoreRowOpStream::next_op has cognitive complexity 37 (threshold 15). Drivers by points: if/else 7 (19 pts), match/switch 4 (11 pts), loops 3 (7 pts) (nesting depth added 23). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogStoreRowOpStream::into_vnode_log_store_item_stream (cognitive 21) src/stream/src/common/log_store_impl/kv_log_store/serde.rs:618— LogStoreRowOpStream::into_vnode_log_store_item_stream has cognitive complexity 21 (threshold 15). Drivers by points: if/else 6 (16 pts), match/switch 2 (4 pts), loops 1 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SortExecutor::do_execute (cognitive 34) src/batch/executors/src/executor/order_by.rs:115— SortExecutor::do_execute has cognitive complexity 34 (threshold 15). Drivers by points: if/else 10 (19 pts), loops 7 (12 pts), boolean chains 2, match/switch 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SortExecutor::executor_inner (cognitive 16) src/stream/src/executor/eowc/sort.rs:70— SortExecutor::executor_inner has cognitive complexity 16 (threshold 15). Drivers by points: if/else 3 (10 pts), loops 2 (4 pts), match/switch 1 (2 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TableWatermarksIndex::rewrite_range_with_table_watermark (cognitive 33) src/storage/hummock_sdk/src/table_watermark.rs:118— TableWatermarksIndex::rewrite_range_with_table_watermark has cognitive complexity 33 (threshold 15). Drivers by points: if/else 7 (17 pts), match/switch 5 (16 pts) (nesting depth added 21). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TableWatermarksIndex::filter_regress_watermarks (cognitive 28) src/storage/hummock_sdk/src/table_watermark.rs:173— TableWatermarksIndex::filter_regress_watermarks has cognitive complexity 28 (threshold 15). Drivers by points: if/else 7 (18 pts), loops 3 (6 pts), match/switch 1 (4 pts) (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StageRunner::schedule_tasks (cognitive 32) src/frontend/src/scheduler/distributed/stage.rs:337— StageRunner::schedule_tasks has cognitive complexity 32 (threshold 15). Drivers by points: if/else 9 (16 pts), loops 5 (10 pts), match/switch 2 (5 pts), boolean chains 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StageRunner::schedule_tasks_for_root (cognitive 19) src/frontend/src/scheduler/distributed/stage.rs:620— StageRunner::schedule_tasks_for_root has cognitive complexity 19 (threshold 15). Drivers by points: if/else 8 (17 pts), loops 1, match/switch 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_hummock_sdk::compaction_group::hummock_version_ext::validate_version (cognitive 32) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:1505— risingwave_hummock_sdk::compaction_group::hummock_version_ext::validate_version has cognitive complexity 32 (threshold 15). Drivers by points: if/else 9 (23 pts), loops 4 (7 pts), boolean chains 2 (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_hummock_sdk::compaction_group::group_split::split_sst_info_for_level_v2 (cognitive 29) src/storage/hummock_sdk/src/compaction_group/mod.rs:376— risingwave_hummock_sdk::compaction_group::group_split::split_sst_info_for_level_v2 has cognitive complexity 29 (threshold 15). Drivers by points: if/else 12 (25 pts), match/switch 2 (4 pts) (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StreamReaderBuilder::into_retry_stream (cognitive 31) src/stream/src/executor/source/reader_stream.rs:234— StreamReaderBuilder::into_retry_stream has cognitive complexity 31 (threshold 15). Drivers by points: if/else 13 (22 pts), match/switch 2 (6 pts), loops 2 (3 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StreamReaderBuilder::setup_auto_schema_change (cognitive 17) src/stream/src/executor/source/reader_stream.rs:103— StreamReaderBuilder::setup_auto_schema_change has cognitive complexity 17 (threshold 15). Drivers by points: if/else 6 (11 pts), match/switch 1 (4 pts), loops 1 (2 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ScalarAdapter::into_scalar (cognitive 30) src/connector/src/parser/scalar_adapter.rs:302— ScalarAdapter::into_scalar has cognitive complexity 30 (threshold 15). Drivers by points: if/else 5 (12 pts), match/switch 4 (12 pts), loops 3 (6 pts) (nesting depth added 18). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ScalarAdapter::from_scalar (cognitive 20) src/connector/src/parser/scalar_adapter.rs:223— ScalarAdapter::from_scalar has cognitive complexity 20 (threshold 15). Drivers by points: match/switch 4 (10 pts), loops 3 (8 pts), if/else 1 (2 pts) (nesting depth added 12). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_rt::logger::init_risingwave_logger (cognitive 30) src/utils/runtime/src/logger.rs:235— risingwave_rt::logger::init_risingwave_logger has cognitive complexity 30 (threshold 15). Drivers by points: if/else 15 (20 pts), match/switch 4 (7 pts), loops 1 (2 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_rt::main_okk (cognitive 16) src/utils/runtime/src/lib.rs:69— risingwave_rt::main_okk has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (11 pts), match/switch 3 (5 pts) (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Command::reschedule_to_mutation (cognitive 29) src/meta/src/barrier/command.rs:1187— Command::reschedule_to_mutation has cognitive complexity 29 (threshold 15). Drivers by points: loops 10 (18 pts), if/else 4 (11 pts) (nesting depth added 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
Command::collect_database_partial_graph_actor_upstreams (cognitive 27) src/meta/src/barrier/command.rs:1698— Command::collect_database_partial_graph_actor_upstreams has cognitive complexity 27 (threshold 15). Drivers by points: loops 7 (20 pts), if/else 2 (6 pts), boolean chains 1 (nesting depth added 17). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
ScheduledBarriers::mark_ready (cognitive 26) src/meta/src/barrier/schedule.rs:635— ScheduledBarriers::mark_ready has cognitive complexity 26 (threshold 15). Drivers by points: if/else 9 (19 pts), loops 2 (4 pts), boolean chains 2, match/switch 1 (nesting depth added 12). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ScheduledBarriers::abort_and_mark_blocked (cognitive 21) src/meta/src/barrier/schedule.rs:575— ScheduledBarriers::abort_and_mark_blocked has cognitive complexity 21 (threshold 15). Drivers by points: if/else 8 (16 pts), loops 2 (3 pts), match/switch 1 (2 pts) (nesting depth added 10). Of this number, 20 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
EowcOverWindowExecutor::apply_chunk (cognitive 26) src/stream/src/executor/over_window/eowc.rs:411— EowcOverWindowExecutor::apply_chunk has cognitive complexity 26 (threshold 15). Drivers by points: loops 7 (18 pts), if/else 4 (7 pts), boolean chains 1 (nesting depth added 14). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
EowcOverWindowExecutor::executor_inner (cognitive 26) src/stream/src/executor/over_window/eowc.rs:544— EowcOverWindowExecutor::executor_inner has cognitive complexity 26 (threshold 15). Drivers by points: if/else 8 (20 pts), boolean chains 3, match/switch 1 (2 pts), loops 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DataChunkMutator::remove_duplicate_rows_for_left_semi_anti_join (cognitive 25) src/batch/executors/src/executor/join/hash_join.rs:2132— DataChunkMutator::remove_duplicate_rows_for_left_semi_anti_join has cognitive complexity 25 (threshold 15). Drivers by points: if/else 7 (17 pts), boolean chains 4, loops 3 (4 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DataChunkMutator::remove_duplicate_rows_for_full_outer_join (cognitive 16) src/batch/executors/src/executor/join/hash_join.rs:2224— DataChunkMutator::remove_duplicate_rows_for_full_outer_join has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (10 pts), loops 4 (5 pts), boolean chains 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_connector_codec::decoder::protobuf::parser::from_protobuf_value (cognitive 24) src/connector/codec/src/decoder/protobuf/parser.rs:106— risingwave_connector_codec::decoder::protobuf::parser::from_protobuf_value has cognitive complexity 24 (threshold 15). Drivers by points: if/else 7 (16 pts), loops 3 (7 pts), match/switch 1 (nesting depth added 13). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_connector_codec::decoder::avro::schema::avro_type_mapping (cognitive 23) src/connector/codec/src/decoder/avro/schema.rs:101— risingwave_connector_codec::decoder::avro::schema::avro_type_mapping has cognitive complexity 23 (threshold 15). Drivers by points: if/else 8 (16 pts), match/switch 3 (5 pts), boolean chains 2 (nesting depth added 10). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
risingwave_cmd_all::standalone::standalone (cognitive 23) src/cmd_all/src/standalone.rs:241— risingwave_cmd_all::standalone::standalone has cognitive complexity 23 (threshold 15). Drivers by points: if/else 14 (18 pts), loops 2 (4 pts), match/switch 1 (nesting depth added 6). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
risingwave_cmd_all::single_node::map_single_node_opts_to_standalone_opts (cognitive 21) src/cmd_all/src/single_node.rs:124— risingwave_cmd_all::single_node::map_single_node_opts_to_standalone_opts has cognitive complexity 21 (threshold 15). Drivers by points: if/else 18 (20 pts), match/switch 1 (nesting depth added 2). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
LakekeeperService::create_default_warehouse (cognitive 23) REDACTED:250— LakekeeperService::create_default_warehouse has cognitive complexity 23 (threshold 15). Drivers by points: if/else 9 (19 pts), match/switch 1 (2 pts), boolean chains 1, loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LakekeeperService::bootstrap_lakekeeper (cognitive 22) REDACTED:171— LakekeeperService::bootstrap_lakekeeper has cognitive complexity 22 (threshold 15). Drivers by points: if/else 7 (17 pts), boolean chains 2, match/switch 1 (2 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DataCacheRefillTaskGenerator::filter_by_inheritance_filter (cognitive 21) src/storage/src/hummock/event_handler/refiller.rs:784— DataCacheRefillTaskGenerator::filter_by_inheritance_filter has cognitive complexity 21 (threshold 15). Drivers by points: if/else 5 (13 pts), loops 3 (6 pts), match/switch 2 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DataCacheRefillTaskGenerator::generate_unfiltered_tasks (cognitive 20) src/storage/src/hummock/event_handler/refiller.rs:665— DataCacheRefillTaskGenerator::generate_unfiltered_tasks has cognitive complexity 20 (threshold 15). Drivers by points: if/else 9 (15 pts), loops 2 (3 pts), boolean chains 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalScan::try_better_locality (cognitive 20) src/frontend/src/optimizer/plan_node/logical_scan.rs:736— LogicalScan::try_better_locality has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (14 pts), boolean chains 3, loops 2 (3 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalScan::to_stream (cognitive 18) src/frontend/src/optimizer/plan_node/logical_scan.rs:621— LogicalScan::to_stream has cognitive complexity 18 (threshold 15). Drivers by points: if/else 7 (15 pts), boolean chains 3 (nesting depth added 8). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
PostgresExternalTableReader::as_uneven_splits (cognitive 19) src/connector/src/source/cdc/external/postgres.rs:709— PostgresExternalTableReader::as_uneven_splits has cognitive complexity 19 (threshold 15). Drivers by points: if/else 8 (13 pts), match/switch 1 (3 pts), boolean chains 2, loops 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PostgresExternalTableReader::split_filter_expression (cognitive 17) src/connector/src/source/cdc/external/postgres.rs:433— PostgresExternalTableReader::split_filter_expression has cognitive complexity 17 (threshold 15). Drivers by points: if/else 8 (12 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DiagnoseCommand::write_worker_nodes (cognitive 18) src/meta/src/manager/diagnose.rs:239— DiagnoseCommand::write_worker_nodes has cognitive complexity 18 (threshold 15). Drivers by points: if/else 8 (11 pts), boolean chains 3, match/switch 1 (3 pts), loops 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DiagnoseCommand::write_storage (cognitive 17) src/meta/src/manager/diagnose.rs:504— DiagnoseCommand::write_storage has cognitive complexity 17 (threshold 15). Drivers by points: if/else 6 (8 pts), loops 5 (8 pts), boolean chains 1 (nesting depth added 5). Of this number, 13 points are the body's own statements and 4 belong to 2 function items inside it that branch. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MemTable::delete (cognitive 16) src/storage/src/mem_table.rs:204— MemTable::delete has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (11 pts), match/switch 2 (3 pts), boolean chains 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MemTable::update (cognitive 16) src/storage/src/mem_table.rs:285— MemTable::update has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (11 pts), match/switch 2 (3 pts), boolean chains 2 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Change coupling clique: batch_delete.rs, batch_insert.rs, batch_update.rs src/frontend/src/optimizer/plan_node/batch_delete.rs— 3 files — `src/frontend/src/optimizer/plan_node/batch_delete.rs`, `src/frontend/src/optimizer/plan_node/batch_insert.rs`, `src/frontend/src/optimizer/plan_node/batch_update.rs` — all change together with no explicit dependency: a fully-connected co-change clique, not 3 separate couplings. They share one concern (thin parallel siblings over a common abstraction), so extract the shared part into ONE unit and the whole clique's coupling clears at once — you do not need to break each pair individually.
Change coupling clique: compactor_service.rs, compute_node_service.rs, frontend_service.rs, meta_node_service.rs src/risedevtool/src/task/compactor_service.rs— 4 files — `src/risedevtool/src/task/compactor_service.rs`, `src/risedevtool/src/task/compute_node_service.rs`, `src/risedevtool/src/task/frontend_service.rs`, `src/risedevtool/src/task/meta_node_service.rs` — all change together with no explicit dependency: a fully-connected co-change clique, not 6 separate couplings. They share one concern (thin parallel siblings over a common abstraction), so extract the shared part into ONE unit and the whole clique's coupling clears at once — you do not need to break each pair individually.
Near-duplicate member pair (27 shared lines) src/meta/src/controller/streaming_job.rs:3097— src/meta/src/controller/streaming_job.rs:3097-3156 | src/meta/src/controller/streaming_job.rs:3165-3277 — These two members are variants of one another: 27 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (27 shared lines) src/sqlparser/src/parser.rs:3543— src/sqlparser/src/parser.rs:3543-3626 | src/sqlparser/src/parser.rs:3747-3853 — These two members are variants of one another: 27 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Duplicated block (29 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:2475— src/batch/executors/src/executor/join/hash_join.rs:2475-2503 | src/batch/executors/src/executor/join/nested_loop_join.rs:208-236 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (29 lines × 2) src/connector/src/source/cdc/external/postgres.rs:539— src/connector/src/source/cdc/external/postgres.rs:539-567 | src/connector/src/source/cdc/external/postgres.rs:583-611 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (26 lines × 2) src/connector/src/sink/redis.rs:105— src/connector/src/sink/redis.rs:105-130 | src/connector/src/sink/redis.rs:132-157 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (26 lines × 2) src/frontend/src/webhook/websocket.rs:497— src/frontend/src/webhook/websocket.rs:497-522 | src/frontend/src/webhook/websocket.rs:548-573 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (24 lines × 2) src/frontend/src/scheduler/local.rs:363— src/frontend/src/scheduler/local.rs:363-386 | src/frontend/src/scheduler/local.rs:401-424 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (24 lines × 2) src/meta/src/dashboard/prometheus.rs:85— src/meta/src/dashboard/prometheus.rs:85-108 | src/meta/src/dashboard/prometheus.rs:111-134 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (21 lines × 3) src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:325— src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:325-345 | src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:549-569 | src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:707-727 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (21 lines × 3) src/jni_core/src/lib.rs:706— src/jni_core/src/lib.rs:706-739 | src/jni_core/src/lib.rs:811-831 | src/jni_core/src/lib.rs:934-960 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (19–21 lines × 2) src/compute/src/server.rs:517— src/compute/src/server.rs:517-537 | src/storage/compactor/src/server.rs:371-389 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (19–21 lines × 2) src/stream/src/executor/backfill/cdc/cdc_backfill.rs:772— src/stream/src/executor/backfill/cdc/cdc_backfill.rs:772-792 | src/stream/src/executor/backfill/cdc/cdc_backfill.rs:989-1007 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (19 lines × 3) src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:65— src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:65-83 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_files.rs:64-82 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_snapshots.rs:43-61 — before extracting anything, compare `src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs` and `src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_files.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 41 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (19 lines × 3) e2e_test/s3/file_sink.py:130— e2e_test/s3/file_sink.py:130-148 | e2e_test/s3/file_source.py:395-413 | e2e_test/s3/file_source.py:502-520 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (17–19 lines × 2) src/batch/executors/src/executor/delete.rs:179— src/batch/executors/src/executor/delete.rs:179-195 | src/batch/executors/src/executor/update.rs:212-230 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (17–19 lines × 2) src/storage/compactor/src/server.rs:364— src/storage/compactor/src/server.rs:364-380 | src/storage/compactor/src/server.rs:472-490 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15–16 lines × 3) src/frontend/src/optimizer/plan_node/batch_hash_join.rs:107— src/frontend/src/optimizer/plan_node/batch_hash_join.rs:107-121 | src/frontend/src/optimizer/plan_node/batch_lookup_join.rs:131-146 | src/frontend/src/optimizer/plan_node/stream_delta_join.rs:111-126 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (15–16 lines × 3) REDACTED:48— REDACTED:48-62 | REDACTED:67-81 | REDACTED:223-238 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (15 lines × 3) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:169— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:169-183 | src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:193-207 | src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:251-265 — before extracting anything, compare `src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs` and `src/stream/src/executor/source/batch_source/batch_iceberg_list.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 89 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (15 lines × 3) src/stream/src/executor/source/mod.rs:137— src/stream/src/executor/source/mod.rs:137-151 | src/stream/src/executor/source/mod.rs:162-176 | src/stream/src/executor/source/mod.rs:228-242 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (13–15 lines × 2) src/connector/src/source/cdc/external/mysql.rs:853— src/connector/src/source/cdc/external/mysql.rs:853-867 | src/connector/src/source/cdc/external/mysql.rs:870-882 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13–15 lines × 2) src/risedevtool/src/task/frontend_service.rs:68— src/risedevtool/src/task/frontend_service.rs:68-82 | src/risedevtool/src/task/meta_node_service.rs:100-112 — before extracting anything, compare `src/risedevtool/src/task/frontend_service.rs` and `src/risedevtool/src/task/meta_node_service.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 36 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (12–14 lines × 3) src/frontend/src/optimizer/plan_node/logical_dedup.rs:197— src/frontend/src/optimizer/plan_node/logical_dedup.rs:197-208 | src/frontend/src/optimizer/plan_node/logical_gap_fill.rs:122-135 | src/frontend/src/optimizer/plan_node/logical_topn.rs:264-277 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (12–14 lines × 3) src/stream/src/common/table/state_table.rs:1538— src/stream/src/common/table/state_table.rs:1538-1550 | src/stream/src/common/table/state_table.rs:1562-1573 | src/stream/src/common/table/state_table.rs:1586-1599 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (12 lines × 5) src/frontend/src/catalog/system_catalog/rw_catalog/rw_connections.rs:38— src/frontend/src/catalog/system_catalog/rw_catalog/rw_connections.rs:38-49 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_functions.rs:42-53 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_materialized_views.rs:44-55 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_secrets.rs:34-45 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_tables.rs:41-52 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 5 call sites, so a change lands once.
Duplicated block (12 lines × 5) src/meta/src/manager/diagnose.rs:385— src/meta/src/manager/diagnose.rs:385-396 | src/meta/src/manager/diagnose.rs:399-410 | src/meta/src/manager/diagnose.rs:413-424 | src/meta/src/manager/diagnose.rs:427-438 | src/meta/src/manager/diagnose.rs:441-452 — all 5 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (12 lines × 4) src/frontend/src/metrics_reader.rs:103— src/frontend/src/metrics_reader.rs:103-114 | src/frontend/src/metrics_reader.rs:132-143 | src/meta/src/dashboard/mod.rs:876-887 | src/meta/src/dashboard/mod.rs:903-914 — before extracting anything, compare `src/frontend/src/metrics_reader.rs` and `src/meta/src/dashboard/mod.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 42 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (12 lines × 4) src/frontend/src/optimizer/plan_node/logical_dedup.rs:200— src/frontend/src/optimizer/plan_node/logical_dedup.rs:200-211 | src/frontend/src/optimizer/plan_node/logical_gap_fill.rs:127-138 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:283-294 | src/frontend/src/optimizer/plan_node/logical_topn.rs:269-280 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 4 call sites, so a change lands once.
Duplicated block (11–12 lines × 3) src/frontend/src/handler/show.rs:988— src/frontend/src/handler/show.rs:988-999 | src/frontend/src/handler/show.rs:1062-1072 | src/frontend/src/handler/show.rs:1132-1142 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (11–12 lines × 3) src/stream/src/executor/over_window/over_partition.rs:1012— src/stream/src/executor/over_window/over_partition.rs:1012-1022 | src/stream/src/executor/over_window/over_partition.rs:1044-1055 | src/stream/src/executor/over_window/over_partition.rs:1088-1099 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10–11 lines × 3) src/expr/core/src/aggregate/user_defined.rs:157— src/expr/core/src/aggregate/user_defined.rs:157-166 | src/expr/core/src/expr/expr_udf.rs:175-185 | src/expr/core/src/table_function/user_defined.rs:129-138 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (10–11 lines × 3) src/meta/src/hummock/compaction/selector/space_reclaim_selector.rs:57— src/meta/src/hummock/compaction/selector/space_reclaim_selector.rs:57-67 | src/meta/src/hummock/compaction/selector/tombstone_compaction_selector.rs:58-68 | src/meta/src/hummock/compaction/selector/ttl_selector.rs:54-63 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (10 lines × 5) src/frontend/src/optimizer/plan_node/batch_hash_join.rs:108— src/frontend/src/optimizer/plan_node/batch_hash_join.rs:108-117 | src/frontend/src/optimizer/plan_node/batch_lookup_join.rs:132-141 | src/frontend/src/optimizer/plan_node/stream_asof_join.rs:216-225 | src/frontend/src/optimizer/plan_node/stream_delta_join.rs:112-121 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:540-549 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/stream_asof_join.rs` and `src/frontend/src/optimizer/plan_node/stream_hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 57 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10 lines × 5) src/meta/src/controller/streaming_job.rs:1273— src/meta/src/controller/streaming_job.rs:1273-1282 | src/meta/src/controller/streaming_job.rs:1310-1319 | src/meta/src/controller/streaming_job.rs:1791-1800 | src/meta/src/controller/streaming_job.rs:1897-1906 | src/meta/src/controller/streaming_job.rs:2309-2318 — all 5 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8–10 lines × 2) src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:89— src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:89-96 | src/stream/src/executor/source/iceberg_list_executor.rs:108-117 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (8–10 lines × 2) REDACTED:316— REDACTED:316-323 | REDACTED:345-354 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at `REDACTED:345` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (6–8 lines × 4) src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:75— src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:75-80 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:98-103 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:120-127 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:152-159 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (6–8 lines × 4) src/frontend/src/optimizer/plan_node/logical_agg.rs:632— src/frontend/src/optimizer/plan_node/logical_agg.rs:632-639 | src/frontend/src/optimizer/plan_node/logical_agg.rs:684-691 | src/frontend/src/optimizer/plan_node/logical_agg.rs:694-701 | src/frontend/src/optimizer/plan_node/logical_agg.rs:703-708 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (7–8 lines × 3) src/connector/src/connector_common/iceberg/mod.rs:683— src/connector/src/connector_common/iceberg/mod.rs:683-689 | src/connector/src/connector_common/iceberg/mod.rs:1042-1049 | src/connector/src/connector_common/iceberg/mod.rs:1071-1078 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (7–8 lines × 3) REDACTED:318— REDACTED:318-324 | REDACTED:349-355 | REDACTED:412-419 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. Read the line range as the matched WINDOW rather than a finished unit: at `REDACTED:412` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just before the matched lines, `REDACTED:347` calls `execute_insert` and `REDACTED:412` does not — after which the two agree again for 3 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
Duplicated block (6–7 lines × 4) src/connector/src/sink/iceberg/writer.rs:391— src/connector/src/sink/iceberg/writer.rs:391-396 | src/connector/src/sink/iceberg/writer.rs:526-531 | src/connector/src/sink/iceberg/writer.rs:556-562 | src/connector/src/sink/iceberg/writer.rs:585-591 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (6–7 lines × 4) integration_tests/iceberg-cdc/python/script/init.py:92— integration_tests/iceberg-cdc/python/script/init.py:92-98 | integration_tests/iceberg-sink2/python/main.py:107-112 | integration_tests/iceberg-source/python/main.py:82-87 | integration_tests/iceberg-source/python/main.py:99-105 — there are 4 copies across 3 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 4 sites; resolving a subset leaves the remainder to drift apart. Read the line range as the matched WINDOW rather than a finished unit: at `integration_tests/iceberg-cdc/python/script/init.py:92` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just before the matched lines, `integration_tests/iceberg-sink2/python/main.py:107` calls `connect` and `integration_tests/iceberg-cdc/python/script/init.py:92` does not — after which the two agree again for 2 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
Duplicated block (7 lines × 4) src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:790— src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:790-796 | src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:829-835 | src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:854-860 | src/storage/src/hummock/compactor/iceberg_compaction/iceberg_compactor_runner.rs:873-879 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (7 lines × 4) REDACTED:458— REDACTED:458-464 | REDACTED:469-475 | REDACTED:492-498 | REDACTED:503-509 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (6 lines × 4) src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:75— src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:75-80 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:98-103 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:120-125 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs:177-182 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (6 lines × 4) REDACTED:648— REDACTED:648-653 | src/connector/src/sink/doris.rs:307-312 | src/connector/src/sink/postgres.rs:217-222 | src/connector/src/sink/sqlserver.rs:166-171 — before extracting anything, compare `src/connector/src/sink/doris.rs` and `src/connector/src/sink/sqlserver.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 36 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (5–6 lines × 2) src/frontend/src/planner/relation.rs:661— src/frontend/src/planner/relation.rs:661-665 | src/frontend/src/planner/relation.rs:687-692 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (5–6 lines × 2) src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:188— src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:188-193 | src/stream/src/executor/source/batch_source/batch_posix_fs_fetch.rs:236-240 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5 lines × 5) src/meta/src/controller/catalog/mod.rs:1119— src/meta/src/controller/catalog/mod.rs:1119-1127 | src/meta/src/controller/catalog/mod.rs:1279-1283 | src/meta/src/controller/catalog/mod.rs:1311-1319 | src/meta/src/controller/catalog/mod.rs:1323-1330 | src/meta/src/controller/catalog/mod.rs:1334-1342 — all 5 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 5) src/frontend/src/optimizer/plan_node/logical_changelog.rs:256— src/frontend/src/optimizer/plan_node/logical_changelog.rs:256-260 | src/frontend/src/optimizer/plan_node/logical_expand.rs:190-194 | src/frontend/src/optimizer/plan_node/logical_filter.rs:220-224 | src/frontend/src/optimizer/plan_node/logical_locality_provider.rs:155-159 | src/frontend/src/optimizer/plan_node/logical_max_one_row.rs:118-122 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 5 call sites, so a change lands once.
Duplicated block (6 lines × 5) src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_config.rs:173— src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_config.rs:173-178 | src/connector/src/sink/kafka.rs:272-277 | src/connector/src/sink/kinesis.rs:158-163 | src/connector/src/sink/pulsar.rs:200-205 | src/connector/src/sink/redis.rs:254-259 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 5 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 5 times.
Duplicated block (6 lines × 5) REDACTED:319— REDACTED:319-324 | REDACTED:350-355 | REDACTED:414-419 | REDACTED:423-428 | REDACTED:432-437 — all 5 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just before the matched lines, `REDACTED:347` calls `execute_insert` and `REDACTED:412` does not — after which the two agree again for 2 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
Duplicated block (10 lines × 2 locations) dashboard/components/FragmentGraph.tsx:148— dashboard/components/FragmentGraph.tsx:148 · dashboard/components/RelationGraph.tsx:92 — the 2 copies sit in sibling files in one directory, so check first whether one of them (or an existing module there) already owns this behaviour and the others should call it; otherwise extract it into one module in that directory and have each site call it.
Duplicated block (10 lines × 2 locations) dashboard/components/utils/backPressure.tsx:19— dashboard/components/utils/backPressure.tsx:19 · dashboard/components/utils/backPressure.tsx:73 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (9 lines × 2 locations) dashboard/components/FragmentGraph.tsx:509— dashboard/components/FragmentGraph.tsx:509 · dashboard/components/RelationGraph.tsx:203 — the 2 copies are spread across 2 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
Duplicated block (9 lines × 2 locations) dashboard/pages/fragment_graph.tsx:403— dashboard/pages/fragment_graph.tsx:403 · dashboard/pages/fragment_graph.tsx:414 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
AC2 · Forms & labels· <NumberInput> field component without a label · ×1
<NumberInput> field component without a label dashboard/pages/cpu_profiling.tsx:199— This UI-library field component has no label / aria-label / aria-labelledby / id / name — and neither does anything it renders — so it likely renders an unlabelled control. Name it whichever way this library supports: a label prop, an aria-label, or an id on the rendered control with a <label htmlFor> pointing at it. For a group of controls, name the group itself (aria-label, or a fieldset with a legend) — labelling each item leaves the set unnamed.
AC7 · A11y enforcement· Accessibility enforcement below the top rung · ×1
Accessibility enforcement below the top rung — No accessibility enforcement found — no a11y linter (eslint-plugin-jsx-a11y) and no axe/pa11y/Lighthouse in tests or CI. Start with the linter to catch issues at author time. What was searched, so you can tell an absence from a miss: the 24 markup file(s) this pass actually assessed, the linter configuration checked in beside them, and this repository's test and CI files — matched by name against the accessibility checkers this dimension carries. An audit run outside the repository, a hosted scanner, or a check whose name is not one of those, is not seen here.
Statement::fmt_unchecked (cyclomatic 148) src/sqlparser/src/ast/mod.rs:1801— Statement::fmt_unchecked has cyclomatic complexity 148 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ParallelizedCdcBackfillExecutor::execute_inner (cyclomatic 90) src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:114— ParallelizedCdcBackfillExecutor::execute_inner has cyclomatic complexity 90 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
JsonParseOptions::parse (cyclomatic 74) src/connector/src/parser/unified/json.rs:277— JsonParseOptions::parse has cyclomatic complexity 74 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
IcebergCommon::build_jni_catalog_configs (cyclomatic 71) src/connector/src/connector_common/iceberg/mod.rs:766— IcebergCommon::build_jni_catalog_configs has cyclomatic complexity 71 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
FrontendObserverNode::handle_catalog_notification (cyclomatic 70) src/frontend/src/observer/observer_manager.rs:251— FrontendObserverNode::handle_catalog_notification has cyclomatic complexity 70 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
Expr::fmt (cyclomatic 69) src/sqlparser/src/ast/mod.rs:543— Expr::fmt has cyclomatic complexity 69 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
CdcBackfillExecutor::execute_inner (cyclomatic 64) src/stream/src/executor/backfill/cdc/cdc_backfill.rs:329— CdcBackfillExecutor::execute_inner has cyclomatic complexity 64 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
MaterializeExecutor::execute_inner (cyclomatic 60) src/stream/src/executor/mview/materialize.rs:373— MaterializeExecutor::execute_inner has cyclomatic complexity 60 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SourceBackfillExecutorInner::execute (cyclomatic 59) src/stream/src/executor/source/source_backfill_executor.rs:383— SourceBackfillExecutorInner::execute has cyclomatic complexity 59 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
StatementType::infer_from_statement (cyclomatic 59) src/utils/pgwire/src/pg_response.rs:255— StatementType::infer_from_statement has cyclomatic complexity 59 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
SourceExecutor::execute_inner (cyclomatic 53) src/stream/src/executor/source/source_executor.rs:616— SourceExecutor::execute_inner has cyclomatic complexity 53 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
AvroParseOptionsInner::convert_to_datum (cyclomatic 49) src/connector/codec/src/decoder/avro/mod.rs:88— AvroParseOptionsInner::convert_to_datum has cyclomatic complexity 49 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
StreamSink::create (cyclomatic 49) src/frontend/src/optimizer/plan_node/stream_sink.rs:280— StreamSink::create has cyclomatic complexity 49 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
BeMessage::write (cyclomatic 49) src/utils/pgwire/src/pg_message.rs:496— BeMessage::write has cyclomatic complexity 49 (threshold 15). Of this number, 43 points are the body's own statements and 6 belong to one function item inside it that branches. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
SqlServerStreamingChangeEventSource.executeIteration (cyclomatic 46) java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/sqlserver/SqlServerStreamingChangeEventSource.java:280— SqlServerStreamingChangeEventSource.executeIteration has cyclomatic complexity 46 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
StreamChunkDeserializer.buildValueGetter (cyclomatic 46) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/deserializer/StreamChunkDeserializer.java:44— StreamChunkDeserializer.buildValueGetter has cyclomatic complexity 46 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
ArrangementBackfillExecutor::execute_inner (cyclomatic 43) src/stream/src/executor/backfill/arrangement_backfill.rs:109— ArrangementBackfillExecutor::execute_inner has cyclomatic complexity 43 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DmlExecutor::execute_inner (cyclomatic 41) src/stream/src/executor/dml.rs:109— DmlExecutor::execute_inner has cyclomatic complexity 41 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
LocalityProviderExecutor::execute_inner (cyclomatic 41) REDACTED:470— LocalityProviderExecutor::execute_inner has cyclomatic complexity 41 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
DbzConnectorConfig.<init> (cyclomatic 41) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/DbzConnectorConfig.java:156— DbzConnectorConfig.<init> has cyclomatic complexity 41 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
MonotonicityAnalyzer::visit_function_call (cyclomatic 40) src/frontend/src/optimizer/property/monotonicity.rs:177— MonotonicityAnalyzer::visit_function_call has cyclomatic complexity 40 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
NavExtractor::rewrite (cyclomatic 38) src/frontend/src/binder/relation/match_recognize.rs:1217— NavExtractor::rewrite has cyclomatic complexity 38 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
WatermarkFilterExecutorInner::execute_inner (cyclomatic 37) src/stream/src/executor/watermark_filter.rs:92— WatermarkFilterExecutorInner::execute_inner has cyclomatic complexity 37 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ClickHouseFieldWithNull::from_scalar_ref (cyclomatic 36) src/connector/src/sink/clickhouse.rs:968— ClickHouseFieldWithNull::from_scalar_ref has cyclomatic complexity 36 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
ListValue::from_str (cyclomatic 33) src/common/src/array/list_array.rs:747— ListValue::from_str has cyclomatic complexity 33 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
PostgresValidator.validatePublicationConfig (cyclomatic 33) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:411— PostgresValidator.validatePublicationConfig has cyclomatic complexity 33 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
FragmentGraph.FragmentGraph (cyclomatic 33) dashboard/components/FragmentGraph.tsx:92— FragmentGraph.FragmentGraph has cyclomatic complexity 33 (threshold 15). Most of this is not in the body itself: 4 of the 33 points are its own statements and the rest belongs to 15 function literals inside it that branch (lines 242, 384, 477, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
ReplayWorker::handle_record (cyclomatic 31) src/storage/hummock_trace/src/replay/worker.rs:161— ReplayWorker::handle_record has cyclomatic complexity 31 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CorrelatedTopNToVectorSearchRule::apply (cyclomatic 30) src/frontend/src/optimizer/rule/correlated_topn_to_vector_search.rs:42— CorrelatedTopNToVectorSearchRule::apply has cyclomatic complexity 30 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
LocalQueryExecution::convert_plan_node (cyclomatic 30) src/frontend/src/scheduler/local.rs:260— LocalQueryExecution::convert_plan_node has cyclomatic complexity 30 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
IcebergConnection::validate_connection (cyclomatic 29) src/connector/src/connector_common/connection.rs:179— IcebergConnection::validate_connection has cyclomatic complexity 29 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SessionTimezone::with_timezone (cyclomatic 29) src/frontend/src/expr/session_timezone.rs:76— SessionTimezone::with_timezone has cyclomatic complexity 29 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
TableFunction::new_file_scan (cyclomatic 29) src/frontend/src/expr/table_function.rs:80— TableFunction::new_file_scan has cyclomatic complexity 29 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
OverWindowExecutor::apply_chunk (cyclomatic 29) src/stream/src/executor/over_window/general.rs:374— OverWindowExecutor::apply_chunk has cyclomatic complexity 29 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SnowflakeV2Config::from_btreemap (cyclomatic 28) src/connector/src/sink/snowflake_redshift/snowflake.rs:230— SnowflakeV2Config::from_btreemap has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ExecutorInner::generate_filled_rows (cyclomatic 28) src/stream/src/executor/eowc/eowc_gap_fill.rs:84— ExecutorInner::generate_filled_rows has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
extract.process_file (cyclomatic 28) docs/metrics/extract.py:399— extract.process_file has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
KafkaConnectionProps::set_security_properties (cyclomatic 27) src/connector/src/connector_common/common.rs:518— KafkaConnectionProps::set_security_properties has cyclomatic complexity 27 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
KafkaSplitReader::into_data_event_stream (cyclomatic 27) src/connector/src/source/kafka/source/reader.rs:376— KafkaSplitReader::into_data_event_stream has cyclomatic complexity 27 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SpecificParserConfig::new (cyclomatic 26) src/connector/src/parser/config.rs:124— SpecificParserConfig::new has cyclomatic complexity 26 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
RedisSink::validate (cyclomatic 26) src/connector/src/sink/redis.rs:325— RedisSink::validate has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
NonOverlapSubLevelPicker::pick_sub_level (cyclomatic 26) src/meta/src/hummock/compaction/picker/non_overlap_sub_level_picker.rs:159— NonOverlapSubLevelPicker::pick_sub_level has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SnapshotBackfillExecutor::execute_inner (cyclomatic 26) src/stream/src/executor/backfill/snapshot_backfill/executor.rs:163— SnapshotBackfillExecutor::execute_inner has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
extract.split_top_args (cyclomatic 26) docs/metrics/extract.py:96— extract.split_top_args has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SourceStreamChunkRowWriter::do_action (cyclomatic 25) src/connector/src/parser/chunk_builder.rs:272— SourceStreamChunkRowWriter::do_action has cyclomatic complexity 25 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
WaitCheckpointTask::run_with_on_commit_success (cyclomatic 25) src/connector/src/source/mod.rs:160— WaitCheckpointTask::run_with_on_commit_success has cyclomatic complexity 25 (threshold 15). Of this number, 20 points are the body's own statements and 5 belong to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CoordinatedLogSinker::consume_log_and_sink (cyclomatic 24) src/connector/src/sink/coordinate.rs:75— CoordinatedLogSinker::consume_log_and_sink has cyclomatic complexity 24 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
IcebergConfig::from_btreemap (cyclomatic 24) src/connector/src/sink/iceberg/config.rs:578— IcebergConfig::from_btreemap has cyclomatic complexity 24 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
Unit::from_str (cyclomatic 24) src/expr/impl/src/scalar/extract.rs:263— Unit::from_str has cyclomatic complexity 24 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
NowExecutor::execute_inner (cyclomatic 24) src/stream/src/executor/now.rs:97— NowExecutor::execute_inner has cyclomatic complexity 24 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
PartitionCache::shrink (cyclomatic 24) src/stream/src/executor/over_window/range_cache.rs:185— PartitionCache::shrink has cyclomatic complexity 24 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
RelationGraph.RelationGraph (cyclomatic 24) dashboard/components/RelationGraph.tsx:73— RelationGraph.RelationGraph has cyclomatic complexity 24 (threshold 15). Most of this is not in the body itself: 1 of the 24 points is its own statement and the rest belongs to 9 function literals inside it that branch (lines 255, 283, 206, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
BuildingFragment::fill_job (cyclomatic 23) src/meta/src/stream/stream_graph/fragment.rs:140— BuildingFragment::fill_job has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
BatchOpendalFsFetchExecutor::into_stream (cyclomatic 23) src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:186— BatchOpendalFsFetchExecutor::into_stream has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
BatchPosixFsFetchExecutor::into_stream (cyclomatic 23) src/stream/src/executor/source/batch_source/batch_posix_fs_fetch.rs:234— BatchPosixFsFetchExecutor::into_stream has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
FsFetchExecutor::into_stream (cyclomatic 23) src/stream/src/executor/source/fs_fetch_executor.rs:294— FsFetchExecutor::into_stream has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ResultCache::consume (cyclomatic 23) src/utils/pgwire/src/pg_extended.rs:47— ResultCache::consume has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
fragment_graph.Streaming (cyclomatic 23) dashboard/pages/fragment_graph.tsx:227— fragment_graph.Streaming has cyclomatic complexity 23 (threshold 15). Most of this is not in the body itself: 7 of the 23 points are its own statements and the rest belongs to 7 function literals inside it that branch (lines 299, 317, 262, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
LookupJoinBase::do_execute (cyclomatic 22) src/batch/executors/src/executor/join/lookup_join_base.rs:77— LookupJoinBase::do_execute has cyclomatic complexity 22 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
risingwave_expr::scalar::like::like_impl (cyclomatic 22) src/expr/core/src/scalar/like.rs:22— risingwave_expr::scalar::like::like_impl has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
BooleanConstantFolding::rewrite_function_call (cyclomatic 22) src/frontend/src/expr/utils.rs:172— BooleanConstantFolding::rewrite_function_call has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
PullUpHopRule::apply (cyclomatic 22) src/frontend/src/optimizer/rule/pull_up_hop_rule.rs:25— PullUpHopRule::apply has cyclomatic complexity 22 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
PostCollectCommand::post_collect (cyclomatic 22) src/meta/src/barrier/context/context_impl.rs:634— PostCollectCommand::post_collect has cyclomatic complexity 22 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
Scheduler::schedule (cyclomatic 22) src/meta/src/stream/stream_graph/schedule.rs:164— Scheduler::schedule has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
HopWindowExecutor::execute_inner (cyclomatic 22) src/stream/src/executor/hop_window.rs:72— HopWindowExecutor::execute_inner has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
extract.find_matching_paren (cyclomatic 22) docs/metrics/extract.py:43— extract.find_matching_paren has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
heap_profiling.HeapProfiling (cyclomatic 22) dashboard/pages/heap_profiling.tsx:75— heap_profiling.HeapProfiling has cyclomatic complexity 22 (threshold 15). Most of this is not in the body itself: 10 of the 22 points are its own statements and the rest belongs to 4 function literals inside it that branch (lines 93, 87, 130, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
DataChunk::from_pretty (cyclomatic 21) src/common/src/array/data_chunk.rs:713— DataChunk::from_pretty has cyclomatic complexity 21 (threshold 15). Most of this is not in the body itself: 7 of the 21 points are its own statements and the rest belongs to one function item inside it that branches (parse_type). Those helpers are already separate functions, so extracting the branching again is not available. To reduce it, move them out of the body to the enclosing scope, where each is measured, reviewed and tested on its own, and reduce whichever one then reads as the largest.
ScanRange::range_overlap_check (cyclomatic 20) src/common/src/util/scan_range.rs:139— ScanRange::range_overlap_check has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
MySqlExternalTableReader::snapshot_read_inner (cyclomatic 20) src/connector/src/source/cdc/external/mysql.rs:767— MySqlExternalTableReader::snapshot_read_inner has cyclomatic complexity 20 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions. This is NOT this file's highest cyclomatic complexity: risingwave_connector::source::cdc::external::mysql::type_name_to_mysql_type (cyclomatic 49) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
NatsPropertiesConsumer::set_config (cyclomatic 20) src/connector/src/source/nats/mod.rs:224— NatsPropertiesConsumer::set_config has cyclomatic complexity 20 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
IcebergIntermediateScanRule::apply (cyclomatic 20) src/frontend/src/optimizer/rule/iceberg_intermediate_scan_rule.rs:60— IcebergIntermediateScanRule::apply has cyclomatic complexity 20 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
StageRunner::schedule_tasks (cyclomatic 20) src/frontend/src/scheduler/distributed/stage.rs:337— StageRunner::schedule_tasks has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
InflightDatabaseInfo::apply_collected_command (cyclomatic 20) src/meta/src/barrier/info.rs:625— InflightDatabaseInfo::apply_collected_command has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
PartialGraphManager::next_event_inner (cyclomatic 20) src/meta/src/barrier/partial_graph.rs:723— PartialGraphManager::next_event_inner has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
IcebergCompactionManager::apply_sink_update (cyclomatic 20) src/meta/src/manager/iceberg_compaction/schedule.rs:803— IcebergCompactionManager::apply_sink_update has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
CoordinatorWorker::run_coordination (cyclomatic 20) src/meta/src/manager/sink_coordination/coordinator_worker.rs:670— CoordinatorWorker::run_coordination has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
UserOptions::parse_to (cyclomatic 20) src/sqlparser/src/ast/statement.rs:1120— UserOptions::parse_to has cyclomatic complexity 20 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
UpstreamTableExecutor::into_stream (cyclomatic 20) src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/executor.rs:115— UpstreamTableExecutor::into_stream has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
TemporalJoinExecutor::into_stream (cyclomatic 20) src/stream/src/executor/temporal_join.rs:666— TemporalJoinExecutor::into_stream has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
cpu_profiling.CpuProfiling (cyclomatic 20) dashboard/pages/cpu_profiling.tsx:68— cpu_profiling.CpuProfiling has cyclomatic complexity 20 (threshold 15). Of this number, 13 points are the body's own statements and 7 belong to 4 function literals inside it that branch. To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
PartialGraphRecoverer::inject_database_initial_barrier (cyclomatic 19) src/meta/src/barrier/rpc.rs:619— PartialGraphRecoverer::inject_database_initial_barrier has cyclomatic complexity 19 (threshold 15). Of this number, 18 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
QueryRewriter::visit_expr (cyclomatic 19) src/meta/src/controller/rename.rs:331— QueryRewriter::visit_expr has cyclomatic complexity 19 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
SpaceReclaimCompactionPicker::pick_compaction (cyclomatic 19) src/meta/src/hummock/compaction/picker/space_reclaim_compaction_picker.rs:59— SpaceReclaimCompactionPicker::pick_compaction has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Matches::try_match (cyclomatic 19) src/meta/src/stream/stream_graph/state_match.rs:240— Matches::try_match has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
TableFactor::fmt (cyclomatic 19) src/sqlparser/src/ast/query.rs:706— TableFactor::fmt has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SstableBuilder::add_impl (cyclomatic 19) src/storage/src/hummock/sstable/builder.rs:351— SstableBuilder::add_impl has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ConsumeUpstreamStream::poll_next (cyclomatic 19) src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/stream.rs:286— ConsumeUpstreamStream::poll_next has cyclomatic complexity 19 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
IcebergFetchExecutor::into_stream (cyclomatic 19) src/stream/src/executor/source/iceberg_fetch_executor.rs:278— IcebergFetchExecutor::into_stream has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
risingwave_rt::logger::init_risingwave_logger (cyclomatic 19) src/utils/runtime/src/logger.rs:235— risingwave_rt::logger::init_risingwave_logger has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
extract.scan_direct_constructions (cyclomatic 19) docs/metrics/extract.py:528— extract.scan_direct_constructions has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
extract.main (cyclomatic 19) docs/metrics/extract.py:661— extract.main has cyclomatic complexity 19 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
FormatError::check_expr (cyclomatic 18) lints/src/format_error.rs:104— FormatError::check_expr has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SortExecutor::do_execute (cyclomatic 18) src/batch/executors/src/executor/order_by.rs:115— SortExecutor::do_execute has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
StackTraceResponseOutput::fmt (cyclomatic 18) src/common/src/util/prost.rs:44— StackTraceResponseOutput::fmt has cyclomatic complexity 18 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
DeltaJoinSolver::find_lookup_path (cyclomatic 18) src/frontend/src/optimizer/delta_join_solver.rs:295— DeltaJoinSolver::find_lookup_path has cyclomatic complexity 18 (threshold 15). Of this number, 14 points are the body's own statements and 4 belong to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Agg::infer_stream_agg_state (cyclomatic 18) src/frontend/src/optimizer/plan_node/generic/agg.rs:394— Agg::infer_stream_agg_state has cyclomatic complexity 18 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function so the top-level body reads as a short sequence of named decisions.
LogicalMultiJoin::as_bushy_tree_join (cyclomatic 18) src/frontend/src/optimizer/plan_node/logical_multi_join.rs:512— LogicalMultiJoin::as_bushy_tree_join has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
IndexDeltaJoinRule::apply (cyclomatic 18) src/frontend/src/optimizer/rule/index_delta_join_rule.rs:25— IndexDeltaJoinRule::apply has cyclomatic complexity 18 (threshold 15). Most of this is not in the body itself: 6 of the 18 points are its own statements and the rest belongs to 2 function items inside it that branch (match_indexes, match_through_exchange). Those helpers are already separate functions, so extracting the branching again is not available. To reduce it, move them out of the body to the enclosing scope, where each is measured, reviewed and tested on its own, and reduce whichever one then reads as the largest.
PullUpCorrelatedPredicateAggRule::apply (cyclomatic 18) src/frontend/src/optimizer/rule/pull_up_correlated_predicate_agg_rule.rs:65— PullUpCorrelatedPredicateAggRule::apply has cyclomatic complexity 18 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
CheckpointControl::handle_new_barrier (cyclomatic 18) src/meta/src/barrier/checkpoint/control.rs:236— CheckpointControl::handle_new_barrier has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
GlobalStreamManager::run (cyclomatic 18) src/meta/src/stream/scale.rs:1412— GlobalStreamManager::run has cyclomatic complexity 18 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
CompactTaskExecutor::run (cyclomatic 18) src/storage/src/hummock/compactor/fast_compactor_runner.rs:698— CompactTaskExecutor::run has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SstableStore::prefetch_blocks (cyclomatic 18) src/storage/src/hummock/sstable_store.rs:341— SstableStore::prefetch_blocks has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
BatchAdbcSnowflakeFetchExecutor::into_stream (cyclomatic 18) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_fetch.rs:75— BatchAdbcSnowflakeFetchExecutor::into_stream has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ManagedTopNState::init_topn_cache_inner (cyclomatic 18) src/stream/src/executor/top_n/top_n_state.rs:201— ManagedTopNState::init_topn_cache_inner has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
doc_issue_tracker.find_tracking_issues (cyclomatic 18) .github/scripts/doc_issue_tracker.py:242— doc_issue_tracker.find_tracking_issues has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
streamingStats.createStreamingStatsRefresh (cyclomatic 18) dashboard/lib/api/streamingStats.ts:48— streamingStats.createStreamingStatsRefresh has cyclomatic complexity 18 (threshold 15). Most of this is not in the body itself: 1 of the 18 points is its own statement and the rest belongs to 3 function literals inside it that branch (lines 69, 104, 54). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
risingwave_cmd_all::single_node::map_single_node_opts_to_standalone_opts (cyclomatic 17) src/cmd_all/src/single_node.rs:124— risingwave_cmd_all::single_node::map_single_node_opts_to_standalone_opts has cyclomatic complexity 17 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
ObserverManager::wait_init_notification (cyclomatic 17) src/common/common_service/src/observer_manager.rs:86— ObserverManager::wait_init_notification has cyclomatic complexity 17 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
TemplateEncoder::build (cyclomatic 17) src/connector/src/sink/formatter/mod.rs:313— TemplateEncoder::build has cyclomatic complexity 17 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing. This is NOT this file's highest cyclomatic complexity: SinkFormatterImpl::new (cyclomatic 27) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
RemoteLogSinker::consume_log_and_sink (cyclomatic 17) src/connector/src/sink/remote.rs:328— RemoteLogSinker::consume_log_and_sink has cyclomatic complexity 17 (threshold 15). Of this number, 13 points are the body's own statements and 4 belong to one function item inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
KinesisSplitReader::into_data_stream (cyclomatic 17) src/connector/src/source/kinesis/source/reader.rs:177— KinesisSplitReader::into_data_stream has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ClusterControllerInner::add_worker (cyclomatic 17) src/meta/src/controller/cluster.rs:615— ClusterControllerInner::add_worker has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
MinOverlappingPicker::pick_tables (cyclomatic 17) src/meta/src/hummock/compaction/picker/min_overlap_compaction_picker.rs:50— MinOverlappingPicker::pick_tables has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
ManualCompactionSelector::pick_compaction (cyclomatic 17) src/meta/src/hummock/compaction/selector/manual_selector.rs:93— ManualCompactionSelector::pick_compaction has cyclomatic complexity 17 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
risingwave_object_store::object::build_remote_object_store (cyclomatic 17) src/object_store/src/object/mod.rs:879— risingwave_object_store::object::build_remote_object_store has cyclomatic complexity 17 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
TableWatermarks::clear_stale_epoch_watermark (cyclomatic 17) src/storage/hummock_sdk/src/table_watermark.rs:563— TableWatermarks::clear_stale_epoch_watermark has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
UploaderData::sync (cyclomatic 17) src/storage/src/hummock/event_handler/uploader/mod.rs:998— UploaderData::sync has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
Nfa::walk (cyclomatic 17) src/stream/src/executor/match_recognize/nfa.rs:1037— Nfa::walk has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
IcebergListExecutor::into_stream (cyclomatic 17) src/stream/src/executor/source/iceberg_list_executor.rs:92— IcebergListExecutor::into_stream has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
RowSeqScanExecutor::do_execute (cyclomatic 16) src/batch/executors/src/executor/row_seq_scan.rs:160— RowSeqScanExecutor::do_execute has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
TableScanIoEstimator::match_index_column (cyclomatic 16) src/frontend/src/optimizer/rule/index_selection_rule.rs:859— TableScanIoEstimator::match_index_column has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: TableScanIoEstimator::estimate_data_type_size (cyclomatic 22) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
TopNToVectorSearchRule::resolve_vector_search (cyclomatic 16) src/frontend/src/optimizer/rule/top_n_to_vector_search_rule.rs:51— TopNToVectorSearchRule::resolve_vector_search has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
UnifyFirstLastValueRule::apply (cyclomatic 16) src/frontend/src/optimizer/rule/unify_first_last_value_rule.rs:87— UnifyFirstLastValueRule::apply has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
BatchPlanFragmenter::new_stage (cyclomatic 16) src/frontend/src/scheduler/plan_fragmenter.rs:1027— BatchPlanFragmenter::new_stage has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SessionManagerImpl::connect_inner (cyclomatic 16) src/frontend/src/session.rs:1653— SessionManagerImpl::connect_inner has cyclomatic complexity 16 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform — the same kind of value, with no behaviour of its own — a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing.
risedev_config::main (cyclomatic 16) src/risedevtool/config/src/main.rs:338— risedev_config::main has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top. This is NOT this file's highest cyclomatic complexity: Components::from_env (cyclomatic 22) is higher and carries no row of its own — it was excluded as a flat dispatcher (a long switch/match over independent cases: many branches, almost no nesting), which this dimension does not treat as a refactor obligation. It is named here so the ranking you see in this file is not mistaken for the whole of it; the excluded function is counted neither in this dimension's figures nor in its score.
risingwave_hummock_sdk::compaction_group::hummock_version_ext::validate_version (cyclomatic 16) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:1505— risingwave_hummock_sdk::compaction_group::hummock_version_ext::validate_version has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SyncLogStoreDispatchExecutor::execute (cyclomatic 16) src/stream/src/executor/dispatch/dispatch_sync_log_store.rs:284— SyncLogStoreDispatchExecutor::execute has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
NestedLoopTemporalJoinExecutor::into_stream (cyclomatic 16) src/stream/src/executor/nested_loop_temporal_join.rs:150— NestedLoopTemporalJoinExecutor::into_stream has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SourceExecutorBuilder::new_boxed_executor (cyclomatic 16) src/stream/src/from_proto/source/trad_source.rs:139— SourceExecutorBuilder::new_boxed_executor has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
SqlServerValidator.validateTableSchema (cyclomatic 16) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java:142— SqlServerValidator.validateTableSchema has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top.
No assertions: CreateAndReadFromTable integration_tests/client-library/csharp/NpgsqlTest.cs:12— This method's body runs code, and no assertion call was recognised in it. Recognised by name: Assert*, *Should*/ShouldBe*, Verify, Expect, Throws, Record, Received/DidNotReceive, MustHaveHappened/MustNotHaveHappened, EnsureSuccessStatusCode and *AndEnsure* — so verification routed through a helper of your own naming, through a base-class or callback object whose members hold the assertions, or through a harness that fails by throwing under some other name, is not visible to this check and is not counted here. Read it as 'no assertion this check knows how to see', and if that is right, add one.
Deprecated module: github.com/aws/aws-sdk-go — `github.com/aws/aws-sdk-go` is required at v1.44.126 in integration_tests/datagen/go.mod, and its author has DEPRECATED the module: "aws-sdk-go is deprecated. Use aws-sdk-go-v2. See https://aws.amazon.com/blogs/developer/announcing-end-of-support-for-aws-sdk-for-go-v1-on-july-31-2025/." A deprecation is declared by the author in the module's own go.mod and applies to the whole module, not to one release, so moving to a newer version of it does not clear this. Follow the replacement the notice names.
TodoComment integration_tests/client-library/csharp/NpgsqlTest.cs:84— // TODO: reading nested arrays is not supported yet. See https://github.com/risingwavelabs/risingwave/pull/15614
ParallelizedCdcBackfillExecutor::execute_inner (cognitive 389) src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:114— ParallelizedCdcBackfillExecutor::execute_inner has cognitive complexity 389 (threshold 15). Drivers by points: if/else 43 (244 pts), match/switch 13 (80 pts), loops 13 (59 pts), boolean chains 6 (nesting depth added 314). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DmlExecutor::execute_inner (cognitive 172) src/stream/src/executor/dml.rs:109— DmlExecutor::execute_inner has cognitive complexity 172 (threshold 15). Drivers by points: if/else 22 (103 pts), loops 10 (54 pts), match/switch 4 (14 pts), boolean chains 1 (nesting depth added 135). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
Statement::fmt_unchecked (cognitive 138) src/sqlparser/src/ast/mod.rs:1801— Statement::fmt_unchecked has cognitive complexity 138 (threshold 15). Drivers by points: if/else 66 (119 pts), match/switch 7 (13 pts), loops 1 (4 pts), boolean chains 2 (nesting depth added 62). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ArrangementBackfillExecutor::execute_inner (cognitive 137) src/stream/src/executor/backfill/arrangement_backfill.rs:109— ArrangementBackfillExecutor::execute_inner has cognitive complexity 137 (threshold 15). Drivers by points: if/else 20 (74 pts), loops 10 (34 pts), match/switch 6 (26 pts), boolean chains 3 (nesting depth added 98). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
LocalityProviderExecutor::execute_inner (cognitive 114) REDACTED:470— LocalityProviderExecutor::execute_inner has cognitive complexity 114 (threshold 15). Drivers by points: if/else 15 (51 pts), loops 10 (32 pts), match/switch 8 (29 pts), boolean chains 2 (nesting depth added 79). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SqlServerStreamingChangeEventSource.executeIteration (cognitive 102) java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/sqlserver/SqlServerStreamingChangeEventSource.java:280— SqlServerStreamingChangeEventSource.executeIteration has cognitive complexity 102 (threshold 15). Drivers by points: if/else 25 (68 pts), loops 5 (12 pts), boolean chains 10, error handling 3 (7 pts), ternaries 2 (5 pts) (nesting depth added 57). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
DbzConnectorConfig.<init> (cognitive 97) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/DbzConnectorConfig.java:156— DbzConnectorConfig.<init> has cognitive complexity 97 (threshold 15). Drivers by points: if/else 29 (82 pts), boolean chains 9, match/switch 1 (4 pts), loops 1, ternaries 1 (nesting depth added 56). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
IcebergCommon::build_jni_catalog_configs (cognitive 96) src/connector/src/connector_common/iceberg/mod.rs:766— IcebergCommon::build_jni_catalog_configs has cognitive complexity 96 (threshold 15). Drivers by points: if/else 53 (79 pts), boolean chains 11, match/switch 3 (5 pts), loops 1 (nesting depth added 28). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
WatermarkFilterExecutorInner::execute_inner (cognitive 94) src/stream/src/executor/watermark_filter.rs:92— WatermarkFilterExecutorInner::execute_inner has cognitive complexity 94 (threshold 15). Drivers by points: if/else 24 (68 pts), match/switch 5 (14 pts), boolean chains 6, loops 2 (6 pts) (nesting depth added 57). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SnapshotBackfillExecutor::execute_inner (cognitive 80) src/stream/src/executor/backfill/snapshot_backfill/executor.rs:163— SnapshotBackfillExecutor::execute_inner has cognitive complexity 80 (threshold 15). Drivers by points: if/else 30 (64 pts), loops 4 (12 pts), match/switch 2 (4 pts) (nesting depth added 44). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
extract.process_file (cognitive 73) docs/metrics/extract.py:399— extract.process_file has cognitive complexity 73 (threshold 15). Drivers by points: if/else 19 (63 pts), boolean chains 8, loops 2 (nesting depth added 44). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
CoordinatedLogSinker::consume_log_and_sink (cognitive 72) src/connector/src/sink/coordinate.rs:75— CoordinatedLogSinker::consume_log_and_sink has cognitive complexity 72 (threshold 15). Drivers by points: if/else 19 (56 pts), match/switch 4 (11 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 46). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
UpstreamTableExecutor::into_stream (cognitive 67) src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/executor.rs:115— UpstreamTableExecutor::into_stream has cognitive complexity 67 (threshold 15). Drivers by points: if/else 16 (52 pts), loops 4 (10 pts), match/switch 1 (4 pts), boolean chains 1 (nesting depth added 45). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
TemporalJoinExecutor::into_stream (cognitive 62) src/stream/src/executor/temporal_join.rs:666— TemporalJoinExecutor::into_stream has cognitive complexity 62 (threshold 15). Drivers by points: if/else 16 (41 pts), loops 5 (18 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 39). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PostgresValidator.validatePublicationConfig (cognitive 62) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:411— PostgresValidator.validatePublicationConfig has cognitive complexity 62 (threshold 15). Drivers by points: if/else 21 (40 pts), loops 10 (18 pts), boolean chains 3, error handling 1 (nesting depth added 27). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
NowExecutor::execute_inner (cognitive 59) src/stream/src/executor/now.rs:97— NowExecutor::execute_inner has cognitive complexity 59 (threshold 15). Drivers by points: if/else 17 (45 pts), loops 3 (6 pts), match/switch 3 (6 pts), boolean chains 2 (nesting depth added 34). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchOpendalFsFetchExecutor::into_stream (cognitive 58) src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:186— BatchOpendalFsFetchExecutor::into_stream has cognitive complexity 58 (threshold 15). Drivers by points: if/else 7 (30 pts), match/switch 5 (19 pts), loops 2 (6 pts), boolean chains 3 (nesting depth added 41). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
FragmentGraph.FragmentGraph (cognitive 56) dashboard/components/FragmentGraph.tsx:92— FragmentGraph.FragmentGraph has cognitive complexity 56 (threshold 15). Drivers by points: if/else 15 (32 pts), ternaries 9 (18 pts), boolean chains 5, loops 1 (nesting depth added 26). Most of this is not in the body itself: 2 of the 56 points are its own statements and the rest belongs to 15 function literals inside it that branch (lines 242, 477, 492, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
PartitionCache::shrink (cognitive 55) src/stream/src/executor/over_window/range_cache.rs:185— PartitionCache::shrink has cognitive complexity 55 (threshold 15). Drivers by points: if/else 16 (37 pts), loops 6 (16 pts), boolean chains 1, match/switch 1 (nesting depth added 31). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PartialGraphManager::next_event_inner (cognitive 54) src/meta/src/barrier/partial_graph.rs:723— PartialGraphManager::next_event_inner has cognitive complexity 54 (threshold 15). Drivers by points: if/else 7 (27 pts), match/switch 7 (25 pts), loops 2 (nesting depth added 38). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
WaitCheckpointTask::run_with_on_commit_success (cognitive 50) src/connector/src/source/mod.rs:160— WaitCheckpointTask::run_with_on_commit_success has cognitive complexity 50 (threshold 15). Drivers by points: if/else 10 (28 pts), loops 5 (12 pts), match/switch 5 (10 pts) (nesting depth added 30). Of this number, 44 points are the body's own statements and 6 belong to one function item inside it that branches. The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
NestedLoopTemporalJoinExecutor::into_stream (cognitive 50) src/stream/src/executor/nested_loop_temporal_join.rs:150— NestedLoopTemporalJoinExecutor::into_stream has cognitive complexity 50 (threshold 15). Drivers by points: if/else 9 (26 pts), loops 6 (21 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 33). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergFetchExecutor::into_stream (cognitive 50) src/stream/src/executor/source/iceberg_fetch_executor.rs:278— IcebergFetchExecutor::into_stream has cognitive complexity 50 (threshold 15). Drivers by points: if/else 6 (27 pts), match/switch 5 (16 pts), loops 2 (5 pts), boolean chains 2 (nesting depth added 35). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchPosixFsFetchExecutor::into_stream (cognitive 49) src/stream/src/executor/source/batch_source/batch_posix_fs_fetch.rs:234— BatchPosixFsFetchExecutor::into_stream has cognitive complexity 49 (threshold 15). Drivers by points: if/else 6 (24 pts), match/switch 4 (15 pts), loops 2 (6 pts), boolean chains 4 (nesting depth added 33). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ListValue::from_str (cognitive 48) src/common/src/array/list_array.rs:747— ListValue::from_str has cognitive complexity 48 (threshold 15). Drivers by points: if/else 19 (32 pts), match/switch 6 (10 pts), loops 5, boolean chains 1 (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergListExecutor::into_stream (cognitive 48) src/stream/src/executor/source/iceberg_list_executor.rs:92— IcebergListExecutor::into_stream has cognitive complexity 48 (threshold 15). Drivers by points: if/else 9 (28 pts), match/switch 5 (16 pts), loops 2 (4 pts) (nesting depth added 32). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
extract.split_top_args (cognitive 48) docs/metrics/extract.py:96— extract.split_top_args has cognitive complexity 48 (threshold 15). Drivers by points: if/else 12 (31 pts), ternaries 2 (8 pts), boolean chains 5, loops 2 (4 pts) (nesting depth added 27). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LocalQueryExecution::convert_plan_node (cognitive 47) src/frontend/src/scheduler/local.rs:260— LocalQueryExecution::convert_plan_node has cognitive complexity 47 (threshold 15). Drivers by points: if/else 10 (22 pts), match/switch 8 (15 pts), loops 3 (9 pts), boolean chains 1 (nesting depth added 25). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
NonOverlapSubLevelPicker::pick_sub_level (cognitive 47) src/meta/src/hummock/compaction/picker/non_overlap_sub_level_picker.rs:159— NonOverlapSubLevelPicker::pick_sub_level has cognitive complexity 47 (threshold 15). Drivers by points: if/else 16 (31 pts), loops 6 (11 pts), boolean chains 5 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CoordinatorWorker::run_coordination (cognitive 47) src/meta/src/manager/sink_coordination/coordinator_worker.rs:670— CoordinatorWorker::run_coordination has cognitive complexity 47 (threshold 15). Drivers by points: if/else 8 (28 pts), match/switch 6 (15 pts), loops 2 (4 pts) (nesting depth added 31). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
JsonParseOptions::parse (cognitive 46) src/connector/src/parser/unified/json.rs:277— JsonParseOptions::parse has cognitive complexity 46 (threshold 15). Drivers by points: match/switch 11 (22 pts), if/else 7 (16 pts), loops 3 (6 pts), boolean chains 2 (nesting depth added 23). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ExecutorInner::generate_filled_rows (cognitive 46) src/stream/src/executor/eowc/eowc_gap_fill.rs:84— ExecutorInner::generate_filled_rows has cognitive complexity 46 (threshold 15). Drivers by points: if/else 14 (23 pts), match/switch 9 (18 pts), loops 4 (5 pts) (nesting depth added 19). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
extract.find_matching_paren (cognitive 46) docs/metrics/extract.py:43— extract.find_matching_paren has cognitive complexity 46 (threshold 15). Drivers by points: if/else 11 (30 pts), ternaries 2 (8 pts), boolean chains 4, loops 2 (4 pts) (nesting depth added 27). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ProjectSetExecutor::do_execute (cognitive 45) src/batch/executors/src/executor/project_set.rs:58— ProjectSetExecutor::do_execute has cognitive complexity 45 (threshold 15). Drivers by points: if/else 6 (22 pts), loops 6 (16 pts), match/switch 1 (5 pts), boolean chains 2 (nesting depth added 30). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MonotonicityAnalyzer::visit_function_call (cognitive 45) src/frontend/src/optimizer/property/monotonicity.rs:177— MonotonicityAnalyzer::visit_function_call has cognitive complexity 45 (threshold 15). Drivers by points: match/switch 13 (29 pts), if/else 6 (12 pts), boolean chains 4 (nesting depth added 22). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
SpaceReclaimCompactionPicker::pick_compaction (cognitive 44) src/meta/src/hummock/compaction/picker/space_reclaim_compaction_picker.rs:59— SpaceReclaimCompactionPicker::pick_compaction has cognitive complexity 44 (threshold 15). Drivers by points: if/else 12 (34 pts), loops 4 (8 pts), boolean chains 2 (nesting depth added 26). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SyncLogStoreDispatchExecutor::execute (cognitive 44) src/stream/src/executor/dispatch/dispatch_sync_log_store.rs:284— SyncLogStoreDispatchExecutor::execute has cognitive complexity 44 (threshold 15). Drivers by points: if/else 9 (24 pts), match/switch 4 (12 pts), loops 3 (7 pts), boolean chains 1 (nesting depth added 27). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ResultCache::consume (cognitive 44) src/utils/pgwire/src/pg_extended.rs:47— ResultCache::consume has cognitive complexity 44 (threshold 15). Drivers by points: if/else 12 (20 pts), loops 5 (12 pts), match/switch 3 (8 pts), boolean chains 4 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ReplayWorker::handle_record (cognitive 42) src/storage/hummock_trace/src/replay/worker.rs:161— ReplayWorker::handle_record has cognitive complexity 42 (threshold 15). Drivers by points: if/else 23 (37 pts), match/switch 3 (5 pts) (nesting depth added 16). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ChangeLogExecutor::execute_keyed (cognitive 42) src/stream/src/executor/changelog.rs:134— ChangeLogExecutor::execute_keyed has cognitive complexity 42 (threshold 15). Drivers by points: if/else 7 (29 pts), loops 4 (11 pts), match/switch 1 (2 pts) (nesting depth added 30). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LookupJoinBase::do_execute (cognitive 40) src/batch/executors/src/executor/join/lookup_join_base.rs:77— LookupJoinBase::do_execute has cognitive complexity 40 (threshold 15). Drivers by points: loops 8 (20 pts), if/else 5 (13 pts), match/switch 2 (6 pts), boolean chains 1 (nesting depth added 24). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
RedisSink::validate (cognitive 40) src/connector/src/sink/redis.rs:325— RedisSink::validate has cognitive complexity 40 (threshold 15). Drivers by points: if/else 11 (25 pts), boolean chains 13, match/switch 1 (2 pts) (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_expr::scalar::like::like_impl (cognitive 40) src/expr/core/src/scalar/like.rs:22— risingwave_expr::scalar::like::like_impl has cognitive complexity 40 (threshold 15). Drivers by points: if/else 7 (25 pts), boolean chains 11, match/switch 1 (3 pts), loops 1 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CorrelatedTopNToVectorSearchRule::apply (cognitive 40) src/frontend/src/optimizer/rule/correlated_topn_to_vector_search.rs:42— CorrelatedTopNToVectorSearchRule::apply has cognitive complexity 40 (threshold 15). Drivers by points: if/else 25 (32 pts), boolean chains 3, match/switch 2 (3 pts), loops 2 (nesting depth added 8). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
PartialGraphManagedBarrierState::fmt (cognitive 40) src/stream/src/task/barrier_worker/managed_state.rs:123— PartialGraphManagedBarrierState::fmt has cognitive complexity 40 (threshold 15). Drivers by points: if/else 7 (23 pts), loops 5 (15 pts), match/switch 1 (2 pts) (nesting depth added 27). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Expr::fmt (cognitive 39) src/sqlparser/src/ast/mod.rs:543— Expr::fmt has cognitive complexity 39 (threshold 15). Drivers by points: if/else 11 (22 pts), match/switch 6 (9 pts), loops 4 (8 pts) (nesting depth added 18). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
TableWatermarks::clear_stale_epoch_watermark (cognitive 39) src/storage/hummock_sdk/src/table_watermark.rs:563— TableWatermarks::clear_stale_epoch_watermark has cognitive complexity 39 (threshold 15). Drivers by points: if/else 8 (18 pts), loops 7 (18 pts), boolean chains 2, match/switch 1 (nesting depth added 21). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ColumnDeduplicater::dedup (cognitive 39) src/stream/src/executor/aggregate/distinct.rs:67— ColumnDeduplicater::dedup has cognitive complexity 39 (threshold 15). Drivers by points: if/else 11 (29 pts), loops 4 (8 pts), match/switch 1 (2 pts) (nesting depth added 23). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchAdbcSnowflakeFetchExecutor::into_stream (cognitive 39) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_fetch.rs:75— BatchAdbcSnowflakeFetchExecutor::into_stream has cognitive complexity 39 (threshold 15). Drivers by points: if/else 4 (19 pts), match/switch 4 (15 pts), boolean chains 4, loops 1 (nesting depth added 26). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergConnection::validate_connection (cognitive 38) src/connector/src/connector_common/connection.rs:179— IcebergConnection::validate_connection has cognitive complexity 38 (threshold 15). Drivers by points: if/else 23 (32 pts), boolean chains 3, match/switch 2 (3 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
KinesisSinkPayloadWriter::finish (cognitive 38) src/connector/src/sink/kinesis.rs:233— KinesisSinkPayloadWriter::finish has cognitive complexity 38 (threshold 15). Drivers by points: if/else 14 (32 pts), loops 2 (3 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DeltaJoinSolver::find_lookup_path (cognitive 38) src/frontend/src/optimizer/delta_join_solver.rs:295— DeltaJoinSolver::find_lookup_path has cognitive complexity 38 (threshold 15). Drivers by points: if/else 8 (20 pts), loops 8 (16 pts), boolean chains 2 (nesting depth added 20). Of this number, 33 points are the body's own statements and 5 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
InflightDatabaseInfo::apply_collected_command (cognitive 38) src/meta/src/barrier/info.rs:625— InflightDatabaseInfo::apply_collected_command has cognitive complexity 38 (threshold 15). Drivers by points: if/else 13 (28 pts), loops 4 (5 pts), match/switch 2 (4 pts), boolean chains 1 (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergCompactionManager::apply_sink_update (cognitive 38) src/meta/src/manager/iceberg_compaction/schedule.rs:803— IcebergCompactionManager::apply_sink_update has cognitive complexity 38 (threshold 15). Drivers by points: if/else 17 (32 pts), boolean chains 5, match/switch 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CursorWithDelta::move_impl (cognitive 38) src/utils/delta_btree_map/src/lib.rs:181— CursorWithDelta::move_impl has cognitive complexity 38 (threshold 15). Drivers by points: if/else 14 (28 pts), match/switch 3 (9 pts), loops 1 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TableFunction::new_file_scan (cognitive 37) src/frontend/src/expr/table_function.rs:80— TableFunction::new_file_scan has cognitive complexity 37 (threshold 15). Drivers by points: if/else 13 (17 pts), match/switch 6 (11 pts), boolean chains 5, loops 3 (4 pts) (nesting depth added 10). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
FrontendObserverNode::handle_catalog_notification (cognitive 37) src/frontend/src/observer/observer_manager.rs:251— FrontendObserverNode::handle_catalog_notification has cognitive complexity 37 (threshold 15). Drivers by points: match/switch 18 (24 pts), if/else 4 (11 pts), loops 1 (2 pts) (nesting depth added 14). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
BeMessage::write (cognitive 37) src/utils/pgwire/src/pg_message.rs:496— BeMessage::write has cognitive complexity 37 (threshold 15). Drivers by points: match/switch 7 (14 pts), loops 6 (13 pts), if/else 5 (10 pts) (nesting depth added 19). Of this number, 30 points are the body's own statements and 7 belong to one function item inside it that branches. The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
fragment_graph.Streaming (cognitive 37) dashboard/pages/fragment_graph.tsx:227— fragment_graph.Streaming has cognitive complexity 37 (threshold 15). Drivers by points: if/else 11 (20 pts), loops 5 (12 pts), boolean chains 5 (nesting depth added 16). Most of this is not in the body itself: 5 of the 37 points are its own statements and the rest belongs to 7 function literals inside it that branch (lines 299, 317, 262, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
AvroParseOptionsInner::convert_to_datum (cognitive 36) src/connector/codec/src/decoder/avro/mod.rs:88— AvroParseOptionsInner::convert_to_datum has cognitive complexity 36 (threshold 15). Drivers by points: if/else 12 (23 pts), match/switch 4 (7 pts), loops 3 (6 pts) (nesting depth added 17). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Matches::try_match (cognitive 36) src/meta/src/stream/stream_graph/state_match.rs:240— Matches::try_match has cognitive complexity 36 (threshold 15). Drivers by points: if/else 11 (26 pts), loops 4 (7 pts), boolean chains 3 (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchPosixFsListExecutor::into_stream (cognitive 35) src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs:207— BatchPosixFsListExecutor::into_stream has cognitive complexity 35 (threshold 15). Drivers by points: match/switch 5 (22 pts), if/else 3 (11 pts), boolean chains 1, loops 1 (nesting depth added 25). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ManagedTopNState::init_topn_cache_inner (cognitive 35) src/stream/src/executor/top_n/top_n_state.rs:201— ManagedTopNState::init_topn_cache_inner has cognitive complexity 35 (threshold 15). Drivers by points: if/else 12 (22 pts), loops 5 (10 pts), boolean chains 3 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
extract.scan_direct_constructions (cognitive 35) docs/metrics/extract.py:528— extract.scan_direct_constructions has cognitive complexity 35 (threshold 15). Drivers by points: if/else 13 (30 pts), loops 3, boolean chains 2 (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
FormatError::check_expr (cognitive 34) lints/src/format_error.rs:104— FormatError::check_expr has cognitive complexity 34 (threshold 15). Drivers by points: if/else 12 (25 pts), boolean chains 5, loops 2 (4 pts) (nesting depth added 15). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
ParquetParser::convert_record_batch_to_stream_chunk (cognitive 34) src/connector/src/parser/parquet_parser.rs:105— ParquetParser::convert_record_batch_to_stream_chunk has cognitive complexity 34 (threshold 15). Drivers by points: if/else 7 (19 pts), loops 2 (7 pts), match/switch 2 (7 pts), boolean chains 1 (nesting depth added 22). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SessionTimezone::with_timezone (cognitive 34) src/frontend/src/expr/session_timezone.rs:76— SessionTimezone::with_timezone has cognitive complexity 34 (threshold 15). Drivers by points: if/else 8 (17 pts), boolean chains 9, match/switch 3 (6 pts), loops 1 (2 pts) (nesting depth added 13). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ActiveStreamingWorkerNodes::changed (cognitive 34) src/meta/src/manager/metadata.rs:116— ActiveStreamingWorkerNodes::changed has cognitive complexity 34 (threshold 15). Drivers by points: if/else 11 (30 pts), match/switch 1 (2 pts), boolean chains 1, loops 1 (nesting depth added 20). Of this number, 33 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
extract.unescape_rust_string (cognitive 34) docs/metrics/extract.py:168— extract.unescape_rust_string has cognitive complexity 34 (threshold 15). Drivers by points: if/else 10 (27 pts), loops 2 (5 pts), boolean chains 2 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
RemoteLogSinker::consume_log_and_sink (cognitive 33) src/connector/src/sink/remote.rs:328— RemoteLogSinker::consume_log_and_sink has cognitive complexity 33 (threshold 15). Drivers by points: if/else 7 (19 pts), match/switch 4 (10 pts), loops 3, boolean chains 1 (nesting depth added 18). Of this number, 29 points are the body's own statements and 4 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
NavExtractor::rewrite (cognitive 33) src/frontend/src/binder/relation/match_recognize.rs:1217— NavExtractor::rewrite has cognitive complexity 33 (threshold 15). Drivers by points: loops 11 (23 pts), if/else 3 (5 pts), match/switch 2 (4 pts), boolean chains 1 (nesting depth added 16). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
PartialGraphRecoverer::inject_database_initial_barrier (cognitive 33) src/meta/src/barrier/rpc.rs:619— PartialGraphRecoverer::inject_database_initial_barrier has cognitive complexity 33 (threshold 15). Drivers by points: if/else 13 (20 pts), loops 10 (13 pts) (nesting depth added 10). Of this number, 32 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ControlStreamManager::poll_next_event (cognitive 33) src/meta/src/barrier/rpc.rs:430— ControlStreamManager::poll_next_event has cognitive complexity 33 (threshold 15). Drivers by points: if/else 6 (18 pts), match/switch 5 (13 pts), boolean chains 1, loops 1 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CompleteStreamFragmentGraph::build_helper (cognitive 33) src/meta/src/stream/stream_graph/fragment.rs:1741— CompleteStreamFragmentGraph::build_helper has cognitive complexity 33 (threshold 15). Drivers by points: if/else 7 (15 pts), match/switch 3 (11 pts), loops 3 (7 pts) (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LookupExecutor::execute_inner (cognitive 33) src/stream/src/executor/lookup/impl_.rs:226— LookupExecutor::execute_inner has cognitive complexity 33 (threshold 15). Drivers by points: if/else 7 (17 pts), loops 5 (14 pts), match/switch 1 (2 pts) (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Nfa::walk (cognitive 33) src/stream/src/executor/match_recognize/nfa.rs:1037— Nfa::walk has cognitive complexity 33 (threshold 15). Drivers by points: if/else 14 (27 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SyncedKvLogStoreExecutor::execute_inner (cognitive 33) src/stream/src/executor/sync_kv_log_store.rs:743— SyncedKvLogStoreExecutor::execute_inner has cognitive complexity 33 (threshold 15). Drivers by points: if/else 8 (20 pts), match/switch 3 (9 pts), loops 2 (3 pts), boolean chains 1 (nesting depth added 19). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
doc_issue_tracker.find_tracking_issues (cognitive 33) .github/scripts/doc_issue_tracker.py:242— doc_issue_tracker.find_tracking_issues has cognitive complexity 33 (threshold 15). Drivers by points: if/else 7 (19 pts), loops 5 (9 pts), boolean chains 4, error handling 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ConnectorSourceWorker::run (cognitive 32) src/meta/src/stream/source_manager/worker.rs:383— ConnectorSourceWorker::run has cognitive complexity 32 (threshold 15). Drivers by points: if/else 6 (24 pts), match/switch 2 (6 pts), boolean chains 1, loops 1 (nesting depth added 22). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
EowcGapFillExecutor::execute_inner (cognitive 32) src/stream/src/executor/eowc/eowc_gap_fill.rs:348— EowcGapFillExecutor::execute_inner has cognitive complexity 32 (threshold 15). Drivers by points: if/else 6 (21 pts), loops 3 (9 pts), match/switch 1 (2 pts) (nesting depth added 22). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LookupUnionExecutor::execute_inner (cognitive 32) src/stream/src/executor/lookup_union.rs:56— LookupUnionExecutor::execute_inner has cognitive complexity 32 (threshold 15). Drivers by points: if/else 5 (15 pts), loops 5 (9 pts), match/switch 2 (8 pts) (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PullUpHopRule::apply (cognitive 31) src/frontend/src/optimizer/rule/pull_up_hop_rule.rs:25— PullUpHopRule::apply has cognitive complexity 31 (threshold 15). Drivers by points: if/else 20 (22 pts), boolean chains 9 (nesting depth added 2). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
Scheduler::schedule (cognitive 31) src/meta/src/stream/stream_graph/schedule.rs:164— Scheduler::schedule has cognitive complexity 31 (threshold 15). Drivers by points: if/else 8 (17 pts), match/switch 4 (9 pts), loops 5 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BufferChunks::poll_next (cognitive 31) src/stream/src/executor/merge.rs:427— BufferChunks::poll_next has cognitive complexity 31 (threshold 15). Drivers by points: if/else 10 (24 pts), loops 2 (5 pts), match/switch 1 (2 pts) (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DynamicReceivers::poll_next (cognitive 31) src/stream/src/executor/mod.rs:1545— DynamicReceivers::poll_next has cognitive complexity 31 (threshold 15). Drivers by points: if/else 8 (25 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 20). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchIcebergListExecutor::into_stream (cognitive 31) src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:74— BatchIcebergListExecutor::into_stream has cognitive complexity 31 (threshold 15). Drivers by points: match/switch 4 (15 pts), if/else 4 (14 pts), boolean chains 1, loops 1 (nesting depth added 21). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
JDBCSink.write (cognitive 31) java/connector-node/risingwave-sink-jdbc/src/main/java/com/risingwave/connector/JDBCSink.java:148— JDBCSink.write has cognitive complexity 31 (threshold 15). Drivers by points: if/else 9 (23 pts), error handling 2 (5 pts), loops 2 (3 pts) (nesting depth added 18). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ClickHouseFieldWithNull::from_scalar_ref (cognitive 30) src/connector/src/sink/clickhouse.rs:968— ClickHouseFieldWithNull::from_scalar_ref has cognitive complexity 30 (threshold 15). Drivers by points: if/else 16 (22 pts), loops 2 (4 pts), match/switch 2 (3 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergIntermediateScanRule::apply (cognitive 30) src/frontend/src/optimizer/rule/iceberg_intermediate_scan_rule.rs:60— IcebergIntermediateScanRule::apply has cognitive complexity 30 (threshold 15). Drivers by points: if/else 15 (18 pts), match/switch 3 (6 pts), loops 2 (4 pts), boolean chains 2 (nesting depth added 8). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
FilterArithmeticRewriter::simplify_arithmetic_comparison (cognitive 30) src/frontend/src/optimizer/rule/over_window_to_topn_rule.rs:226— FilterArithmeticRewriter::simplify_arithmetic_comparison has cognitive complexity 30 (threshold 15). Drivers by points: if/else 10 (22 pts), match/switch 2 (5 pts), boolean chains 3 (nesting depth added 15). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
LevelCompactionPicker::pick_multi_level_to_base (cognitive 30) src/meta/src/hummock/compaction/picker/base_level_compaction_picker.rs:159— LevelCompactionPicker::pick_multi_level_to_base has cognitive complexity 30 (threshold 15). Drivers by points: if/else 10 (21 pts), loops 5 (9 pts) (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MinOverlappingPicker::pick_tables (cognitive 30) src/meta/src/hummock/compaction/picker/min_overlap_compaction_picker.rs:50— MinOverlappingPicker::pick_tables has cognitive complexity 30 (threshold 15). Drivers by points: if/else 7 (16 pts), loops 6 (11 pts), boolean chains 3 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SqlBackendElectionClient::run_once (cognitive 30) src/meta/src/rpc/election/sql.rs:651— SqlBackendElectionClient::run_once has cognitive complexity 30 (threshold 15). Drivers by points: if/else 9 (23 pts), match/switch 2 (4 pts), loops 2, boolean chains 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SstableStore::prefetch_blocks (cognitive 30) src/storage/src/hummock/sstable_store.rs:341— SstableStore::prefetch_blocks has cognitive complexity 30 (threshold 15). Drivers by points: if/else 12 (23 pts), boolean chains 3, loops 2 (3 pts), match/switch 1 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockReadVersion::update (cognitive 30) src/storage/src/hummock/store/version.rs:371— HummockReadVersion::update has cognitive complexity 30 (threshold 15). Drivers by points: if/else 11 (24 pts), match/switch 2 (4 pts), loops 1 (2 pts) (nesting depth added 16). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
pgwire::pg_protocol::parse_options (cognitive 30) src/utils/pgwire/src/pg_protocol.rs:1634— pgwire::pg_protocol::parse_options has cognitive complexity 30 (threshold 15). Drivers by points: if/else 15 (28 pts), loops 2 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PullUpCorrelatedPredicateAggRule::apply (cognitive 29) src/frontend/src/optimizer/rule/pull_up_correlated_predicate_agg_rule.rs:65— PullUpCorrelatedPredicateAggRule::apply has cognitive complexity 29 (threshold 15). Drivers by points: if/else 20 (24 pts), loops 3, boolean chains 2 (nesting depth added 4). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
PostCollectCommand::post_collect (cognitive 29) src/meta/src/barrier/context/context_impl.rs:634— PostCollectCommand::post_collect has cognitive complexity 29 (threshold 15). Drivers by points: if/else 9 (17 pts), loops 2 (6 pts), match/switch 3 (5 pts), boolean chains 1 (nesting depth added 14). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
BatchTableInnerIterInner::into_stream (cognitive 29) src/storage/src/table/batch_table/mod.rs:1383— BatchTableInnerIterInner::into_stream has cognitive complexity 29 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 3 (8 pts), match/switch 3 (8 pts), boolean chains 1 (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LocalApproxPercentileExecutor::execute_inner (cognitive 29) src/stream/src/executor/approx_percentile/local.rs:49— LocalApproxPercentileExecutor::execute_inner has cognitive complexity 29 (threshold 15). Drivers by points: if/else 5 (13 pts), match/switch 4 (9 pts), loops 3 (7 pts) (nesting depth added 17). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ScanRange::range_overlap_check (cognitive 28) src/common/src/util/scan_range.rs:139— ScanRange::range_overlap_check has cognitive complexity 28 (threshold 15). Drivers by points: if/else 14 (19 pts), match/switch 5 (6 pts), boolean chains 3 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TombstoneReclaimCompactionPicker::pick_compaction (cognitive 28) src/meta/src/hummock/compaction/picker/tombstone_reclaim_compaction_picker.rs:47— TombstoneReclaimCompactionPicker::pick_compaction has cognitive complexity 28 (threshold 15). Drivers by points: if/else 7 (19 pts), loops 3 (7 pts), boolean chains 2 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BuildingFragment::fill_job (cognitive 28) src/meta/src/stream/stream_graph/fragment.rs:140— BuildingFragment::fill_job has cognitive complexity 28 (threshold 15). Drivers by points: if/else 8 (23 pts), match/switch 2 (3 pts), boolean chains 2 (nesting depth added 16). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
S3ObjectStore::configure_bucket_lifecycle (cognitive 28) src/object_store/src/object/s3.rs:849— S3ObjectStore::configure_bucket_lifecycle has cognitive complexity 28 (threshold 15). Drivers by points: if/else 10 (20 pts), match/switch 1 (4 pts), boolean chains 2, loops 1 (2 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risedev_config::main (cognitive 28) src/risedevtool/config/src/main.rs:338— risedev_config::main has cognitive complexity 28 (threshold 15). Drivers by points: if/else 6 (16 pts), match/switch 4 (7 pts), loops 3 (4 pts), boolean chains 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchTableInner::get_row (cognitive 28) src/storage/src/table/batch_table/mod.rs:569— BatchTableInner::get_row has cognitive complexity 28 (threshold 15). Drivers by points: if/else 7 (14 pts), loops 2 (7 pts), match/switch 3 (6 pts), boolean chains 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchAdbcSnowflakeListExecutor::into_stream (cognitive 28) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:91— BatchAdbcSnowflakeListExecutor::into_stream has cognitive complexity 28 (threshold 15). Drivers by points: match/switch 4 (15 pts), if/else 3 (11 pts), boolean chains 1, loops 1 (nesting depth added 19). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Decimal::checked_powd (cognitive 27) src/common/src/types/decimal.rs:657— Decimal::checked_powd has cognitive complexity 27 (threshold 15). Drivers by points: match/switch 10 (21 pts), if/else 2 (4 pts), boolean chains 2 (nesting depth added 13). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
SnowflakeV2Config::from_btreemap (cognitive 27) src/connector/src/sink/snowflake_redshift/snowflake.rs:230— SnowflakeV2Config::from_btreemap has cognitive complexity 27 (threshold 15). Drivers by points: if/else 12 (17 pts), boolean chains 7, match/switch 2 (3 pts) (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ClusterControllerInner::add_worker (cognitive 27) src/meta/src/controller/cluster.rs:615— ClusterControllerInner::add_worker has cognitive complexity 27 (threshold 15). Drivers by points: if/else 12 (20 pts), match/switch 2 (5 pts), boolean chains 2 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IntraCompactionPicker::pick_l0_intra (cognitive 27) src/meta/src/hummock/compaction/picker/intra_compaction_picker.rs:127— IntraCompactionPicker::pick_l0_intra has cognitive complexity 27 (threshold 15). Drivers by points: if/else 8 (19 pts), loops 4 (7 pts), boolean chains 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CompactionEventLoop::run (cognitive 27) src/meta/src/hummock/manager/compaction/compaction_event_loop.rs:432— CompactionEventLoop::run has cognitive complexity 27 (threshold 15). Drivers by points: if/else 8 (21 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BackwardUserIterator::next (cognitive 27) src/storage/src/hummock/iterator/backward_user.rs:109— BackwardUserIterator::next has cognitive complexity 27 (threshold 15). Drivers by points: if/else 9 (22 pts), match/switch 1 (3 pts), boolean chains 1, loops 1 (nesting depth added 15). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
BatchOpendalFsListExecutor::into_stream (cognitive 27) src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:163— BatchOpendalFsListExecutor::into_stream has cognitive complexity 27 (threshold 15). Drivers by points: match/switch 4 (15 pts), if/else 2 (10 pts), boolean chains 1, loops 1 (nesting depth added 19). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
SourceExecutorBuilder::new_boxed_executor (cognitive 27) src/stream/src/from_proto/source/trad_source.rs:139— SourceExecutorBuilder::new_boxed_executor has cognitive complexity 27 (threshold 15). Drivers by points: if/else 17 (24 pts), boolean chains 3 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
RelationGraph.RelationGraph (cognitive 27) dashboard/components/RelationGraph.tsx:73— RelationGraph.RelationGraph has cognitive complexity 27 (threshold 15). Drivers by points: if/else 13 (16 pts), ternaries 8, boolean chains 3 (nesting depth added 3). Most of this is not in the body itself: 0 of the 27 points are its own statements and the rest belongs to 9 function literals inside it that branch (lines 255, 283, 175, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
BatchTaskExecution::run (cognitive 26) src/batch/src/task/task_execution.rs:517— BatchTaskExecution::run has cognitive complexity 26 (threshold 15). Drivers by points: match/switch 6 (19 pts), if/else 3 (6 pts), loops 1 (nesting depth added 16). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
KafkaConnectionProps::set_security_properties (cognitive 26) src/connector/src/connector_common/common.rs:518— KafkaConnectionProps::set_security_properties has cognitive complexity 26 (threshold 15). Drivers by points: if/else 26. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
IcebergConfig::from_btreemap (cognitive 26) src/connector/src/sink/iceberg/config.rs:578— IcebergConfig::from_btreemap has cognitive complexity 26 (threshold 15). Drivers by points: if/else 19 (22 pts), boolean chains 4 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition.
LogicalOptimizer::register_batch_mview_candidates (cognitive 26) src/frontend/src/optimizer/logical_optimization.rs:958— LogicalOptimizer::register_batch_mview_candidates has cognitive complexity 26 (threshold 15). Drivers by points: if/else 9 (22 pts), loops 3 (4 pts) (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CompactorRunner::merge_inputs (cognitive 26) src/storage/src/hummock/compactor/fast_compactor_runner.rs:462— CompactorRunner::merge_inputs has cognitive complexity 26 (threshold 15). Drivers by points: if/else 8 (20 pts), loops 2 (4 pts), boolean chains 2 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PgCompositeToStringConverter.parsePgTextArray (cognitive 26) java/connector-node/risingwave-source-cdc/src/main/java/com/risingwave/connector/cdc/debezium/converters/PgCompositeToStringConverter.java:182— PgCompositeToStringConverter.parsePgTextArray has cognitive complexity 26 (threshold 15). Drivers by points: if/else 6 (11 pts), loops 3 (7 pts), boolean chains 5, ternaries 1 (3 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StackTraceResponseOutput::fmt (cognitive 25) src/common/src/util/prost.rs:44— StackTraceResponseOutput::fmt has cognitive complexity 25 (threshold 15). Drivers by points: loops 9 (17 pts), if/else 8 (nesting depth added 8). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
BooleanConstantFolding::rewrite_function_call (cognitive 25) src/frontend/src/expr/utils.rs:172— BooleanConstantFolding::rewrite_function_call has cognitive complexity 25 (threshold 15). Drivers by points: if/else 13 (24 pts), match/switch 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
Join::stream_key (cognitive 25) src/frontend/src/optimizer/plan_node/generic/join.rs:305— Join::stream_key has cognitive complexity 25 (threshold 15). Drivers by points: if/else 6 (18 pts), boolean chains 4, match/switch 1 (2 pts), loops 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchPlanFragmenter::new_stage (cognitive 25) src/frontend/src/scheduler/plan_fragmenter.rs:1027— BatchPlanFragmenter::new_stage has cognitive complexity 25 (threshold 15). Drivers by points: if/else 16 (23 pts), boolean chains 1, match/switch 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
WholeLevelCompactionPicker::pick_whole_level (cognitive 25) src/meta/src/hummock/compaction/picker/intra_compaction_picker.rs:339— WholeLevelCompactionPicker::pick_whole_level has cognitive complexity 25 (threshold 15). Drivers by points: if/else 8 (18 pts), boolean chains 4, loops 2 (3 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockCompactorDedicatedEventLoop::compact_task_dedicated_event_handler (cognitive 25) src/meta/src/hummock/manager/compaction/compaction_event_loop.rs:595— HummockCompactorDedicatedEventLoop::compact_task_dedicated_event_handler has cognitive complexity 25 (threshold 15). Drivers by points: if/else 4 (15 pts), match/switch 3 (6 pts), loops 2 (3 pts), boolean chains 1 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergPkIndexSinkCoordinator::resolve_compaction_overwrite_files (cognitive 25) src/meta/src/manager/iceberg_pk_index_sink/coordinator.rs:351— IcebergPkIndexSinkCoordinator::resolve_compaction_overwrite_files has cognitive complexity 25 (threshold 15). Drivers by points: if/else 6 (18 pts), loops 2 (5 pts), boolean chains 2 (nesting depth added 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DollarExpander::visit (cognitive 25) src/risedevtool/src/config/dollar_expander.rs:43— DollarExpander::visit has cognitive complexity 25 (threshold 15). Drivers by points: if/else 4 (11 pts), loops 3 (8 pts), match/switch 2 (6 pts) (nesting depth added 16). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
TableFactor::fmt (cognitive 25) src/sqlparser/src/ast/query.rs:706— TableFactor::fmt has cognitive complexity 25 (threshold 15). Drivers by points: if/else 14 (24 pts), match/switch 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CompactTaskExecutor::run (cognitive 25) src/storage/src/hummock/compactor/fast_compactor_runner.rs:698— CompactTaskExecutor::run has cognitive complexity 25 (threshold 15). Drivers by points: if/else 9 (17 pts), boolean chains 7, loops 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LocalHummockStorage::flush (cognitive 25) src/storage/src/hummock/store/local_hummock_storage.rs:431— LocalHummockStorage::flush has cognitive complexity 25 (threshold 15). Drivers by points: if/else 10 (22 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TroublemakerExecutor::execute_inner (cognitive 25) src/stream/src/executor/troublemaker.rs:55— TroublemakerExecutor::execute_inner has cognitive complexity 25 (threshold 15). Drivers by points: if/else 3 (12 pts), loops 4 (9 pts), match/switch 2 (4 pts) (nesting depth added 16). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
UpdateExecutor::do_execute (cognitive 24) src/batch/executors/src/executor/update.rs:117— UpdateExecutor::do_execute has cognitive complexity 24 (threshold 15). Drivers by points: if/else 10 (17 pts), loops 4 (7 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DataChunk::serialize (cognitive 24) src/common/src/array/data_chunk.rs:527— DataChunk::serialize has cognitive complexity 24 (threshold 15). Drivers by points: loops 6 (14 pts), if/else 5 (10 pts) (nesting depth added 13). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
ApproxPercentile::add_datum (cognitive 24) src/expr/impl/src/aggregate/approx_percentile.rs:84— ApproxPercentile::add_datum has cognitive complexity 24 (threshold 15). Drivers by points: if/else 11 (22 pts), match/switch 1 (2 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SessionWindow::recalculate_left_right (cognitive 24) src/expr/impl/src/window_function/buffer.rs:529— SessionWindow::recalculate_left_right has cognitive complexity 24 (threshold 15). Drivers by points: if/else 11 (23 pts), match/switch 1 (nesting depth added 12). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
IcebergScanInner::execute_inner (cognitive 24) src/frontend/src/datafusion/iceberg_executor.rs:244— IcebergScanInner::execute_inner has cognitive complexity 24 (threshold 15). Drivers by points: if/else 7 (20 pts), loops 2 (3 pts), boolean chains 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalAgg::to_stream (cognitive 24) src/frontend/src/optimizer/plan_node/logical_agg.rs:1435— LogicalAgg::to_stream has cognitive complexity 24 (threshold 15). Drivers by points: if/else 17 (23 pts), boolean chains 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalProject::to_stream_with_dist_required (cognitive 24) src/frontend/src/optimizer/plan_node/logical_project.rs:239— LogicalProject::to_stream_with_dist_required has cognitive complexity 24 (threshold 15). Drivers by points: if/else 12 (17 pts), match/switch 3 (6 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
QueryRewriter::visit_set_expr (cognitive 24) src/meta/src/controller/rename.rs:241— QueryRewriter::visit_set_expr has cognitive complexity 24 (threshold 15). Drivers by points: loops 7 (17 pts), if/else 3 (6 pts), match/switch 1 (nesting depth added 13). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
SstableBuilder::add_impl (cognitive 24) src/storage/src/hummock/sstable/builder.rs:351— SstableBuilder::add_impl has cognitive complexity 24 (threshold 15). Drivers by points: if/else 12 (16 pts), boolean chains 7, match/switch 1 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CapacitySplitTableBuilder::check_switch_builder (cognitive 24) src/storage/src/hummock/sstable/multi_builder.rs:244— CapacitySplitTableBuilder::check_switch_builder has cognitive complexity 24 (threshold 15). Drivers by points: if/else 12 (23 pts), boolean chains 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockStorageReadSnapshot::build_read_version_tuple_from_all (cognitive 24) src/storage/src/hummock/store/hummock_storage.rs:474— HummockStorageReadSnapshot::build_read_version_tuple_from_all has cognitive complexity 24 (threshold 15). Drivers by points: if/else 13 (22 pts), boolean chains 2 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SqlServerValidator.validateTableSchema (cognitive 24) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/SqlServerValidator.java:142— SqlServerValidator.validateTableSchema has cognitive complexity 24 (threshold 15). Drivers by points: if/else 9 (16 pts), loops 6, ternaries 1 (2 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DbzChangeEventConsumer.handleBatch (cognitive 24) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/DbzChangeEventConsumer.java:163— DbzChangeEventConsumer.handleBatch has cognitive complexity 24 (threshold 15). Drivers by points: if/else 6 (13 pts), ternaries 2 (6 pts), error handling 1 (2 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceStreamChunkRowWriter::do_action (cognitive 23) src/connector/src/parser/chunk_builder.rs:272— SourceStreamChunkRowWriter::do_action has cognitive complexity 23 (threshold 15). Drivers by points: if/else 5 (10 pts), match/switch 5 (8 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 10). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Unit::from_str (cognitive 23) src/expr/impl/src/scalar/extract.rs:263— Unit::from_str has cognitive complexity 23 (threshold 15). Drivers by points: if/else 23. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
MetricsReaderImpl::get_channel_delta_stats (cognitive 23) src/frontend/src/metrics_reader.rs:47— MetricsReaderImpl::get_channel_delta_stats has cognitive complexity 23 (threshold 15). Drivers by points: if/else 8 (14 pts), loops 3 (6 pts), boolean chains 3 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
GlobalBarrierWorkerContextImpl::resolve_hummock_version_epochs (cognitive 23) src/meta/src/barrier/context/recovery.rs:727— GlobalBarrierWorkerContextImpl::resolve_hummock_version_epochs has cognitive complexity 23 (threshold 15). Drivers by points: if/else 5 (11 pts), match/switch 2 (6 pts), loops 3 (5 pts), boolean chains 1 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockCompactionEventHandler::try_dispatch_tasks (cognitive 23) src/meta/src/hummock/manager/compaction/compaction_event_loop.rs:300— HummockCompactionEventHandler::try_dispatch_tasks has cognitive complexity 23 (threshold 15). Drivers by points: if/else 6 (13 pts), loops 3 (5 pts), match/switch 2 (4 pts), boolean chains 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IdExpander::visit (cognitive 23) src/risedevtool/src/config/id_expander.rs:52— IdExpander::visit has cognitive complexity 23 (threshold 15). Drivers by points: if/else 5 (15 pts), loops 2 (7 pts), match/switch 1 (nesting depth added 15). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
KvLogStoreReader::next_item (cognitive 23) src/stream/src/common/log_store_impl/kv_log_store/reader.rs:354— KvLogStoreReader::next_item has cognitive complexity 23 (threshold 15). Drivers by points: if/else 7 (15 pts), match/switch 4 (7 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
AppendOnlyDedupExecutor::executor_inner (cognitive 23) src/stream/src/executor/dedup/append_only_dedup.rs:59— AppendOnlyDedupExecutor::executor_inner has cognitive complexity 23 (threshold 15). Drivers by points: if/else 4 (12 pts), match/switch 2 (6 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ConsumerFuture::next_event (cognitive 23) src/stream/src/executor/dispatch/dispatch_sync_log_store.rs:213— ConsumerFuture::next_event has cognitive complexity 23 (threshold 15). Drivers by points: if/else 7 (20 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 14). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BinlogHistoryRecordComparator.isPositionAtOrBefore (cognitive 23) java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/binlog/history/BinlogHistoryRecordComparator.java:74— BinlogHistoryRecordComparator.isPositionAtOrBefore has cognitive complexity 23 (threshold 15). Drivers by points: if/else 11 (22 pts), boolean chains 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StreamChunkDeserializer.buildValueGetter (cognitive 23) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/deserializer/StreamChunkDeserializer.java:44— StreamChunkDeserializer.buildValueGetter has cognitive complexity 23 (threshold 15). Drivers by points: if/else 16, match/switch 3 (6 pts), loops 1 (nesting depth added 3). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
RowSeqScanExecutor::do_execute (cognitive 22) src/batch/executors/src/executor/row_seq_scan.rs:160— RowSeqScanExecutor::do_execute has cognitive complexity 22 (threshold 15). Drivers by points: if/else 7 (13 pts), boolean chains 5, loops 3 (4 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergSplitEnumerator::list_scan_tasks_inner (cognitive 22) src/connector/src/source/iceberg/mod.rs:359— IcebergSplitEnumerator::list_scan_tasks_inner has cognitive complexity 22 (threshold 15). Drivers by points: if/else 5 (15 pts), match/switch 2 (4 pts), loops 2 (3 pts) (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalChangeLog::prune_col (cognitive 22) src/frontend/src/optimizer/plan_node/logical_changelog.rs:120— LogicalChangeLog::prune_col has cognitive complexity 22 (threshold 15). Drivers by points: if/else 13 (18 pts), loops 2 (4 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TrivialMovePicker::pick_multi_trivial_move_ssts (cognitive 22) src/meta/src/hummock/compaction/picker/trivial_move_compaction_picker.rs:53— TrivialMovePicker::pick_multi_trivial_move_ssts has cognitive complexity 22 (threshold 15). Drivers by points: if/else 11 (21 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ManualCompactionSelector::pick_compaction (cognitive 22) src/meta/src/hummock/compaction/selector/manual_selector.rs:93— ManualCompactionSelector::pick_compaction has cognitive complexity 22 (threshold 15). Drivers by points: if/else 15 (18 pts), boolean chains 4 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
risingwave_object_store::object::s3::set_error_should_retry (cognitive 22) src/object_store/src/object/s3.rs:1070— risingwave_object_store::object::s3::set_error_should_retry has cognitive complexity 22 (threshold 15). Drivers by points: if/else 7 (15 pts), match/switch 3 (6 pts), boolean chains 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BackfillExecutor::execute_inner (cognitive 22) src/stream/src/executor/backfill/no_shuffle_backfill.rs:98— BackfillExecutor::execute_inner has cognitive complexity 22 (threshold 15). Drivers by points: if/else 8 (20 pts), loops 2 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
FilterExecutorInner::filter (cognitive 22) src/stream/src/executor/filter.rs:58— FilterExecutorInner::filter has cognitive complexity 22 (threshold 15). Drivers by points: if/else 7 (11 pts), match/switch 3 (10 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IncrementalMatcher::rescan (cognitive 22) src/stream/src/executor/match_recognize/incremental.rs:425— IncrementalMatcher::rescan has cognitive complexity 22 (threshold 15). Drivers by points: if/else 8 (14 pts), loops 4 (6 pts), boolean chains 2 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BatchIcebergFetchExecutor::into_stream (cognitive 22) src/stream/src/executor/source/batch_source/batch_iceberg_fetch.rs:242— BatchIcebergFetchExecutor::into_stream has cognitive complexity 22 (threshold 15). Drivers by points: if/else 3 (11 pts), match/switch 3 (6 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 13). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
FsListExecutor::into_stream (cognitive 22) src/stream/src/executor/source/fs_list_executor.rs:105— FsListExecutor::into_stream has cognitive complexity 22 (threshold 15). Drivers by points: match/switch 4 (15 pts), if/else 2 (6 pts), loops 1 (nesting depth added 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ValuesExecutor::execute_inner (cognitive 22) src/stream/src/executor/values.rs:59— ValuesExecutor::execute_inner has cognitive complexity 22 (threshold 15). Drivers by points: loops 5 (13 pts), if/else 4 (9 pts) (nesting depth added 13). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
extract.main (cognitive 22) docs/metrics/extract.py:661— extract.main has cognitive complexity 22 (threshold 15). Drivers by points: if/else 8 (11 pts), loops 8 (9 pts), boolean chains 1, ternaries 1 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LimitExecutor::do_execute (cognitive 21) src/batch/executors/src/executor/limit.rs:64— LimitExecutor::do_execute has cognitive complexity 21 (threshold 15). Drivers by points: if/else 9 (16 pts), loops 2 (4 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TopNHeap::push (cognitive 21) src/batch/executors/src/executor/top_n.rs:157— TopNHeap::push has cognitive complexity 21 (threshold 15). Drivers by points: if/else 7 (13 pts), loops 1 (4 pts), match/switch 1 (3 pts), boolean chains 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DecoupleCheckpointLogSinkerOf::consume_log_and_sink (cognitive 21) src/connector/src/sink/decouple_checkpoint_log_sink.rs:73— DecoupleCheckpointLogSinkerOf::consume_log_and_sink has cognitive complexity 21 (threshold 15). Drivers by points: if/else 5 (12 pts), match/switch 3 (7 pts), boolean chains 1, loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ElasticSearchOpenSearchFormatter::convert_chunk (cognitive 21) src/connector/src/sink/elasticsearch_opensearch/elasticsearch_opensearch_formatter.rs:118— ElasticSearchOpenSearchFormatter::convert_chunk has cognitive complexity 21 (threshold 15). Drivers by points: if/else 8 (18 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
KinesisSplitReader::into_data_stream (cognitive 21) src/connector/src/source/kinesis/source/reader.rs:177— KinesisSplitReader::into_data_stream has cognitive complexity 21 (threshold 15). Drivers by points: if/else 6 (16 pts), boolean chains 2, match/switch 1 (2 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TableScanIoEstimator::match_index_column (cognitive 21) src/frontend/src/optimizer/rule/index_selection_rule.rs:859— TableScanIoEstimator::match_index_column has cognitive complexity 21 (threshold 15). Drivers by points: if/else 7 (10 pts), boolean chains 5, loops 3, match/switch 1 (3 pts) (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
UnifyFirstLastValueRule::apply (cognitive 21) src/frontend/src/optimizer/rule/unify_first_last_value_rule.rs:87— UnifyFirstLastValueRule::apply has cognitive complexity 21 (threshold 15). Drivers by points: if/else 7 (11 pts), loops 9 (10 pts) (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
JavaLoggerLevelOverrides.parse (cognitive 21) java/connector-node/tracing/src/main/java/com/risingwave/tracing/TracingSlf4jImpl.java:163— JavaLoggerLevelOverrides.parse has cognitive complexity 21 (threshold 15). Drivers by points: if/else 10 (19 pts), boolean chains 1, loops 1 (nesting depth added 9). This file's own header attributes it to another copyright holder, so it is code this repository carries rather than code it wrote: restructuring the body in place forks it from upstream and turns every future re-sync into a manual merge. The performable moves are to leave the body as close to its upstream form as possible and keep it behind a narrow interface of your own, and to re-sync it when upstream changes — or, if it has already diverged far enough that you maintain it here, adopt it deliberately and then split the body into named stages.
heap_profiling.HeapProfiling (cognitive 21) dashboard/pages/heap_profiling.tsx:75— heap_profiling.HeapProfiling has cognitive complexity 21 (threshold 15). Drivers by points: if/else 9, boolean chains 6, error handling 3 (4 pts), loops 1, ternaries 1 (nesting depth added 1). Most of this is not in the body itself: 9 of the 21 points are its own statements and the rest belongs to 4 function literals inside it that branch (lines 93, 130, 87, …). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals' work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest.
StreamChunk::eliminate_adjacent_noop_update (cognitive 20) src/common/src/array/stream_chunk.rs:332— StreamChunk::eliminate_adjacent_noop_update has cognitive complexity 20 (threshold 15). Drivers by points: if/else 6 (11 pts), boolean chains 7, loops 2 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SpecificParserConfig::new (cognitive 20) src/connector/src/parser/config.rs:124— SpecificParserConfig::new has cognitive complexity 20 (threshold 15). Drivers by points: if/else 12 (18 pts), match/switch 2 (nesting depth added 6). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
TemplateEncoder::build (cognitive 20) src/connector/src/sink/formatter/mod.rs:313— TemplateEncoder::build has cognitive complexity 20 (threshold 15). Drivers by points: match/switch 5 (8 pts), boolean chains 6, if/else 2 (6 pts) (nesting depth added 7). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
MySqlExternalTableReader::snapshot_read_inner (cognitive 20) src/connector/src/source/cdc/external/mysql.rs:767— MySqlExternalTableReader::snapshot_read_inner has cognitive complexity 20 (threshold 15). Drivers by points: if/else 8 (12 pts), loops 2 (4 pts), match/switch 1 (3 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
OpendalReader::stream_read_lines (cognitive 20) src/connector/src/source/filesystem/opendal_source/opendal_reader.rs:159— OpendalReader::stream_read_lines has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (11 pts), boolean chains 5, match/switch 3, loops 1 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SomeAllExpression::resolve_bools (cognitive 20) src/expr/core/src/expr/expr_some_all.rs:52— SomeAllExpression::resolve_bools has cognitive complexity 20 (threshold 15). Drivers by points: if/else 6 (12 pts), loops 2 (4 pts), match/switch 2 (4 pts) (nesting depth added 10). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Agg::infer_stream_agg_state (cognitive 20) src/frontend/src/optimizer/plan_node/generic/agg.rs:394— Agg::infer_stream_agg_state has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (12 pts), match/switch 3 (5 pts), loops 3 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StreamKeyChecker::visit_logical_agg (cognitive 20) src/frontend/src/optimizer/plan_visitor/jsonb_stream_key_checker.rs:119— StreamKeyChecker::visit_logical_agg has cognitive complexity 20 (threshold 15). Drivers by points: if/else 4 (11 pts), loops 4 (9 pts) (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ApplyJoinTransposeRule::apply (cognitive 20) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:89— ApplyJoinTransposeRule::apply has cognitive complexity 20 (threshold 15). Drivers by points: if/else 13 (16 pts), boolean chains 3, match/switch 1 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
GroupingSetsToExpandRule::apply (cognitive 20) src/frontend/src/optimizer/rule/grouping_sets_to_expand_rule.rs:72— GroupingSetsToExpandRule::apply has cognitive complexity 20 (threshold 15). Drivers by points: loops 4 (11 pts), if/else 4 (9 pts) (nesting depth added 12). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
OverwriteOptions::new (cognitive 20) src/frontend/src/utils/overwrite_options.rs:33— OverwriteOptions::new has cognitive complexity 20 (threshold 15). Drivers by points: if/else 16 (20 pts) (nesting depth added 4). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
BarrierWorkerRuntimeInfoSnapshot::validate_database_info (cognitive 20) src/meta/src/barrier/mod.rs:154— BarrierWorkerRuntimeInfoSnapshot::validate_database_info has cognitive complexity 20 (threshold 15). Drivers by points: if/else 4 (12 pts), loops 5 (8 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
FragmentActorBuilder::rewrite_inner (cognitive 20) src/meta/src/stream/stream_graph/actor.rs:47— FragmentActorBuilder::rewrite_inner has cognitive complexity 20 (threshold 15). Drivers by points: if/else 6 (12 pts), loops 2 (4 pts), match/switch 2 (3 pts), boolean chains 1 (nesting depth added 9). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
MetaMemberManagement::refresh_members (cognitive 20) src/rpc_client/src/meta_client.rs:2406— MetaMemberManagement::refresh_members has cognitive complexity 20 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 2 (4 pts), match/switch 2 (4 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogStoreBufferReceiver::truncate_buffer (cognitive 20) src/stream/src/common/log_store_impl/kv_log_store/buffer.rs:436— LogStoreBufferReceiver::truncate_buffer has cognitive complexity 20 (threshold 15). Drivers by points: if/else 8 (17 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PositionDeleteMergerExecutor::execute_inner (cognitive 20) src/stream/src/executor/iceberg_with_pk_index/position_delete_merger.rs:98— PositionDeleteMergerExecutor::execute_inner has cognitive complexity 20 (threshold 15). Drivers by points: if/else 4 (12 pts), loops 2 (4 pts), boolean chains 2, match/switch 1 (2 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PostgresStreamingChangeEventSource.commitOffset (cognitive 20) java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:825— PostgresStreamingChangeEventSource.commitOffset has cognitive complexity 20 (threshold 15). Drivers by points: if/else 6 (11 pts), error handling 4 (7 pts), boolean chains 1, ternaries 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
JDBCSqlRunner.executeSqlWithProps (cognitive 20) java/connector-node/risingwave-jdbc-runner/src/main/java/com/risingwave/runner/JDBCSqlRunner.java:31— JDBCSqlRunner.executeSqlWithProps has cognitive complexity 20 (threshold 15). Drivers by points: if/else 5 (9 pts), error handling 3 (6 pts), loops 2 (3 pts), boolean chains 2 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PostgresValidator.validatePublicationPrivileges (cognitive 20) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:654— PostgresValidator.validatePublicationPrivileges has cognitive complexity 20 (threshold 15). Drivers by points: if/else 7 (13 pts), loops 3 (4 pts), boolean chains 3 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PostgresValidator.validateTableSchema (cognitive 20) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:204— PostgresValidator.validateTableSchema has cognitive complexity 20 (threshold 15). Drivers by points: if/else 6 (11 pts), loops 4, ternaries 2 (4 pts), boolean chains 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DeleteExecutor::do_execute (cognitive 19) src/batch/executors/src/executor/delete.rs:111— DeleteExecutor::do_execute has cognitive complexity 19 (threshold 15). Drivers by points: if/else 8 (13 pts), loops 3 (6 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SortAggExecutor::do_execute (cognitive 19) src/batch/executors/src/executor/sort_agg.rs:109— SortAggExecutor::do_execute has cognitive complexity 19 (threshold 15). Drivers by points: if/else 7 (13 pts), loops 3 (5 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SortOverWindowExecutor::do_execute (cognitive 19) src/batch/executors/src/executor/sort_over_window.rs:140— SortOverWindowExecutor::do_execute has cognitive complexity 19 (threshold 15). Drivers by points: loops 4 (10 pts), if/else 4 (9 pts) (nesting depth added 11). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
JsonRef::deref (cognitive 19) src/connector/codec/src/decoder/json/mod.rs:113— JsonRef::deref has cognitive complexity 19 (threshold 15). Drivers by points: if/else 8 (13 pts), boolean chains 2, loops 1 (2 pts), match/switch 1 (2 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MockSinkCoordinationRpcClient::coordinate (cognitive 19) src/connector/src/sink/mock_coordination_client.rs:112— MockSinkCoordinationRpcClient::coordinate has cognitive complexity 19 (threshold 15). Drivers by points: if/else 3 (12 pts), match/switch 3 (6 pts), loops 1 (nesting depth added 12). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MongodbSink::validate (cognitive 19) src/connector/src/sink/mongodb.rs:271— MongodbSink::validate has cognitive complexity 19 (threshold 15). Drivers by points: if/else 11 (15 pts), boolean chains 4 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TurbopufferLogSinker::consume_log_and_sink (cognitive 19) src/connector/src/sink/turbopuffer.rs:347— TurbopufferLogSinker::consume_log_and_sink has cognitive complexity 19 (threshold 15). Drivers by points: if/else 6 (12 pts), match/switch 3 (6 pts), loops 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
NatsPropertiesConsumer::set_config (cognitive 19) src/connector/src/source/nats/mod.rs:224— NatsPropertiesConsumer::set_config has cognitive complexity 19 (threshold 15). Drivers by points: if/else 19. To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
OpenAiEmbedding::eval (cognitive 19) src/expr/impl/src/scalar/ai_model.rs:273— OpenAiEmbedding::eval has cognitive complexity 19 (threshold 15). Drivers by points: if/else 9 (16 pts), loops 2, boolean chains 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ColumnIdGenerator::generate (cognitive 19) src/frontend/src/handler/create_table/col_id_gen.rs:155— ColumnIdGenerator::generate has cognitive complexity 19 (threshold 15). Drivers by points: if/else 8 (11 pts), match/switch 3 (5 pts), loops 1 (2 pts), boolean chains 1 (nesting depth added 6). Most of this is not in the body itself: 7 of the 19 points are its own statements and the rest belongs to one function item inside it that branches (handle). Those helpers are already separate functions, so extracting the branching again is not available. To reduce it, move them out of the body to the enclosing scope, where each is measured, reviewed and tested on its own, and reduce whichever one then reads as the largest.
LogicalOverWindow::convert_window_function (cognitive 19) src/frontend/src/optimizer/plan_node/logical_over_window.rs:301— LogicalOverWindow::convert_window_function has cognitive complexity 19 (threshold 15). Drivers by points: if/else 10 (18 pts), match/switch 1 (nesting depth added 8). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
ExpressionSimplifyRewriter::rewrite_expr (cognitive 19) src/frontend/src/optimizer/rule/logical_filter_expression_simplify_rule.rs:206— ExpressionSimplifyRewriter::rewrite_expr has cognitive complexity 19 (threshold 15). Drivers by points: if/else 12 (16 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
QueryRunner::run (cognitive 19) src/frontend/src/scheduler/distributed/query.rs:294— QueryRunner::run has cognitive complexity 19 (threshold 15). Drivers by points: if/else 3 (10 pts), loops 3 (5 pts), boolean chains 2, match/switch 1 (2 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
BackfillOrderState::finish_fragment (cognitive 19) src/meta/src/barrier/backfill_order_control.rs:240— BackfillOrderState::finish_fragment has cognitive complexity 19 (threshold 15). Drivers by points: if/else 7 (17 pts), loops 1 (2 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StreamFragmentGraph::collect_snapshot_backfill_info_impl (cognitive 19) src/meta/src/stream/stream_graph/fragment.rs:1221— StreamFragmentGraph::collect_snapshot_backfill_info_impl has cognitive complexity 19 (threshold 15). Drivers by points: match/switch 3 (10 pts), if/else 4 (8 pts), loops 1 (nesting depth added 11). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
UnsyncData::clear_tables (cognitive 19) src/storage/src/hummock/event_handler/uploader/mod.rs:946— UnsyncData::clear_tables has cognitive complexity 19 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 3 (7 pts) (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PkPrefixSkipWatermarkState::advance_watermark (cognitive 19) src/storage/src/hummock/iterator/skip_watermark.rs:229— PkPrefixSkipWatermarkState::advance_watermark has cognitive complexity 19 (threshold 15). Drivers by points: match/switch 4 (13 pts), if/else 1 (5 pts), loops 1 (nesting depth added 13). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
RangeKvStateStoreRevIter::next_inner (cognitive 19) src/storage/src/memory.rs:1386— RangeKvStateStoreRevIter::next_inner has cognitive complexity 19 (threshold 15). Drivers by points: if/else 7 (14 pts), boolean chains 2, match/switch 1 (2 pts), loops 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
VectorIndexSnapshot::query_expand_chunk (cognitive 19) src/storage/src/table/batch_table/vector_index_reader.rs:146— VectorIndexSnapshot::query_expand_chunk has cognitive complexity 19 (threshold 15). Drivers by points: if/else 5 (11 pts), loops 3 (7 pts), boolean chains 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DispatchOutputMapping::apply (cognitive 19) src/stream/src/executor/dispatch/output_mapping.rs:60— DispatchOutputMapping::apply has cognitive complexity 19 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 2 (6 pts), match/switch 1 (nesting depth added 11). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
SinkWriterStreamObserver.onNext (cognitive 19) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/SinkWriterStreamObserver.java:94— SinkWriterStreamObserver.onNext has cognitive complexity 19 (threshold 15). Drivers by points: if/else 9 (17 pts), boolean chains 1, error handling 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IcebergScanExecutor::do_execute (cognitive 18) src/batch/executors/src/executor/iceberg_scan.rs:94— IcebergScanExecutor::do_execute has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (14 pts), loops 2 (3 pts), match/switch 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
NestedLoopJoinExecutor::do_full_outer_join (cognitive 18) src/batch/executors/src/executor/join/nested_loop_join.rs:453— NestedLoopJoinExecutor::do_full_outer_join has cognitive complexity 18 (threshold 15). Drivers by points: loops 5 (10 pts), if/else 3 (8 pts) (nesting depth added 10). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
ClickHouseSinkWriter::write (cognitive 18) src/connector/src/sink/clickhouse.rs:746— ClickHouseSinkWriter::write has cognitive complexity 18 (threshold 15). Drivers by points: if/else 6 (12 pts), loops 2 (3 pts), match/switch 1 (2 pts), boolean chains 1 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DynamoDbPayloadWriter::write_chunk (cognitive 18) src/connector/src/sink/dynamodb.rs:525— DynamoDbPayloadWriter::write_chunk has cognitive complexity 18 (threshold 15). Drivers by points: if/else 6 (15 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
KafkaPayloadWriter::send_result (cognitive 18) src/connector/src/sink/kafka.rs:516— KafkaPayloadWriter::send_result has cognitive complexity 18 (threshold 15). Drivers by points: if/else 4 (12 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ExecutorStats::get_delta (cognitive 18) src/frontend/src/handler/explain_analyze_stream_job.rs:376— ExecutorStats::get_delta has cognitive complexity 18 (threshold 15). Drivers by points: if/else 8 (16 pts), loops 2 (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogicalVectorSearch::resolve_vector_index_lookup (cognitive 18) src/frontend/src/optimizer/plan_node/logical_vector_search.rs:364— LogicalVectorSearch::resolve_vector_index_lookup has cognitive complexity 18 (threshold 15). Drivers by points: if/else 6 (13 pts), loops 2 (5 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SessionManagerImpl::connect_inner (cognitive 18) src/frontend/src/session.rs:1653— SessionManagerImpl::connect_inner has cognitive complexity 18 (threshold 15). Drivers by points: match/switch 4 (9 pts), if/else 5 (8 pts), boolean chains 1 (nesting depth added 8). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
CreatingStreamingJobControl::resolve_since_timestamp_upstream_log_epochs (cognitive 18) src/meta/src/barrier/checkpoint/independent_job/creating_job/mod.rs:446— CreatingStreamingJobControl::resolve_since_timestamp_upstream_log_epochs has cognitive complexity 18 (threshold 15). Drivers by points: if/else 9 (13 pts), loops 3 (5 pts) (nesting depth added 6). Of this number, 16 points are the body's own statements and 2 belong to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
RescheduleContext::into_database_contexts (cognitive 18) src/meta/src/barrier/command.rs:210— RescheduleContext::into_database_contexts has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (9 pts), loops 7 (9 pts) (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ClusterController::start_heartbeat_checker (cognitive 18) src/meta/src/controller/cluster.rs:229— ClusterController::start_heartbeat_checker has cognitive complexity 18 (threshold 15). Drivers by points: match/switch 4 (11 pts), loops 3 (5 pts), if/else 1 (2 pts) (nesting depth added 10). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
GrpcMetaClient::start_meta_member_monitor (cognitive 18) src/rpc_client/src/meta_client.rs:2513— GrpcMetaClient::start_meta_member_monitor has cognitive complexity 18 (threshold 15). Drivers by points: if/else 6 (14 pts), match/switch 1 (3 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
VnodeStream::poll_next (cognitive 18) src/stream/src/executor/backfill/snapshot_backfill/vnode_stream.rs:217— VnodeStream::poll_next has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (12 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MergeExecutorInner::execute_inner (cognitive 18) src/stream/src/executor/merge.rs:287— MergeExecutorInner::execute_inner has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (14 pts), match/switch 1 (2 pts), boolean chains 1, loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
RowMergeExecutor::build_chunk (cognitive 18) src/stream/src/executor/row_merge.rs:142— RowMergeExecutor::build_chunk has cognitive complexity 18 (threshold 15). Drivers by points: if/else 6 (11 pts), loops 5 (7 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LdapConfig::from_ldap_url (cognitive 18) src/utils/pgwire/src/ldap_auth.rs:260— LdapConfig::from_ldap_url has cognitive complexity 18 (threshold 15). Drivers by points: if/else 10 (13 pts), boolean chains 4, loops 1 (nesting depth added 3). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
PostgresStreamingChangeEventSource.processReplicationMessages (cognitive 18) java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java:448— PostgresStreamingChangeEventSource.processReplicationMessages has cognitive complexity 18 (threshold 15). Drivers by points: if/else 10 (18 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
PostgresValidator.validatePrivileges (cognitive 18) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java:330— PostgresValidator.validatePrivileges has cognitive complexity 18 (threshold 15). Drivers by points: if/else 5 (10 pts), loops 3 (7 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MergeSortExecutor::do_execute (cognitive 17) src/batch/executors/src/executor/merge_sort.rs:60— MergeSortExecutor::do_execute has cognitive complexity 17 (threshold 15). Drivers by points: loops 4 (7 pts), if/else 2 (6 pts), match/switch 1 (3 pts), boolean chains 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
RateLimitedLogReader::truncate (cognitive 17) src/connector/src/sink/log_store.rs:624— RateLimitedLogReader::truncate has cognitive complexity 17 (threshold 15). Drivers by points: if/else 7 (11 pts), loops 3 (5 pts), boolean chains 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DeliveryFutureManager::next_truncate_offset (cognitive 17) src/connector/src/sink/log_store.rs:903— DeliveryFutureManager::next_truncate_offset has cognitive complexity 17 (threshold 15). Drivers by points: match/switch 3 (11 pts), loops 2 (4 pts), if/else 2 (nesting depth added 10). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
Formatter::from_str (cognitive 17) src/expr/impl/src/scalar/format.rs:132— Formatter::from_str has cognitive complexity 17 (threshold 15). Drivers by points: if/else 9 (15 pts), boolean chains 1, loops 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
risingwave_expr_macro::context::generate_captured_function (cognitive 17) src/expr/macro/src/context.rs:136— risingwave_expr_macro::context::generate_captured_function has cognitive complexity 17 (threshold 15). Drivers by points: if/else 10 (13 pts), match/switch 1 (2 pts), boolean chains 1, loops 1 (nesting depth added 4). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
AggGroupBySimplifyRule::apply (cognitive 17) src/frontend/src/optimizer/rule/agg_group_by_simplify_rule.rs:30— AggGroupBySimplifyRule::apply has cognitive complexity 17 (threshold 15). Drivers by points: if/else 7 (11 pts), loops 3 (6 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
IndexDeltaJoinRule::apply::match_indexes (cognitive 17) src/frontend/src/optimizer/rule/index_delta_join_rule.rs:59— IndexDeltaJoinRule::apply::match_indexes has cognitive complexity 17 (threshold 15). Drivers by points: if/else 9 (14 pts), boolean chains 2, loops 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MvSelectionRule::inner_join_rewrite (cognitive 17) src/frontend/src/optimizer/rule/mv_selection_rule.rs:261— MvSelectionRule::inner_join_rewrite has cognitive complexity 17 (threshold 15). Drivers by points: if/else 9 (16 pts), loops 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ManualCompactionPicker::pick_compaction (cognitive 17) src/meta/src/hummock/compaction/picker/manual_compaction_picker.rs:214— ManualCompactionPicker::pick_compaction has cognitive complexity 17 (threshold 15). Drivers by points: if/else 12 (14 pts), boolean chains 2, loops 1 (nesting depth added 2). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
GlobalRefreshManager::tick (cognitive 17) src/meta/src/stream/refresh_manager.rs:483— GlobalRefreshManager::tick has cognitive complexity 17 (threshold 15). Drivers by points: if/else 7 (13 pts), match/switch 2, boolean chains 1, loops 1 (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
SourceManager::validate_inject_source_offsets (cognitive 17) src/meta/src/stream/source_manager.rs:618— SourceManager::validate_inject_source_offsets has cognitive complexity 17 (threshold 15). Drivers by points: loops 4 (9 pts), if/else 6 (8 pts) (nesting depth added 7). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline.
ValueSkipWatermarkState::should_delete (cognitive 17) src/storage/src/hummock/iterator/skip_watermark.rs:510— ValueSkipWatermarkState::should_delete has cognitive complexity 17 (threshold 15). Drivers by points: if/else 6 (15 pts), match/switch 1 (2 pts) (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
GlobalApproxPercentileState::apply_row (cognitive 17) src/stream/src/executor/approx_percentile/global_state.rs:145— GlobalApproxPercentileState::apply_row has cognitive complexity 17 (threshold 15). Drivers by points: if/else 11 (15 pts), boolean chains 1, match/switch 1 (nesting depth added 4). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
RowIdGenExecutor::gen_row_id_column_by_op (cognitive 17) src/stream/src/executor/row_id_gen.rs:62— RowIdGenExecutor::gen_row_id_column_by_op has cognitive complexity 17 (threshold 15). Drivers by points: if/else 4 (9 pts), match/switch 2 (7 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
WaitCheckpointWorker::run (cognitive 17) src/stream/src/executor/source/source_executor.rs:1267— WaitCheckpointWorker::run has cognitive complexity 17 (threshold 15). Drivers by points: if/else 3 (11 pts), match/switch 2 (5 pts), loops 1 (nesting depth added 11). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
cpu_profiling.CpuProfiling (cognitive 17) dashboard/pages/cpu_profiling.tsx:68— cpu_profiling.CpuProfiling has cognitive complexity 17 (threshold 15). Drivers by points: ternaries 3 (5 pts), boolean chains 4, if/else 4, error handling 2 (3 pts), loops 1 (nesting depth added 3). Of this number, 10 points are the body's own statements and 7 belong to 4 function literals inside it that branch. To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition.
Interval::fmt (cognitive 16) src/common/src/types/interval.rs:1098— Interval::fmt has cognitive complexity 16 (threshold 15). Drivers by points: if/else 9 (12 pts), boolean chains 4 (nesting depth added 3). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DataChunkBuilder::append_chunk_inner (cognitive 16) src/common/src/util/chunk_coalesce.rs:78— DataChunkBuilder::append_chunk_inner has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (12 pts), loops 2 (4 pts) (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ConfigServiceImpl::resize_cache (cognitive 16) src/compute/src/rpc/service/config_service.rs:56— ConfigServiceImpl::resize_cache has cognitive complexity 16 (threshold 15). Drivers by points: if/else 6 (10 pts), match/switch 2 (6 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CsvParser::parse_inner (cognitive 16) src/connector/src/parser/csv_parser.rs:111— CsvParser::parse_inner has cognitive complexity 16 (threshold 15). Drivers by points: if/else 9 (16 pts) (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ExprError::function (cognitive 16) src/expr/core/src/error.rs:143— ExprError::function has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (8 pts), loops 2 (4 pts), match/switch 1 (4 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
EitherOnConflict::to_behavior (cognitive 16) src/frontend/src/handler/create_table.rs:675— EitherOnConflict::to_behavior has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (11 pts), match/switch 2 (4 pts), boolean chains 1 (nesting depth added 8). The drivers above price the dispatch low by construction — a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full — so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
PushCalculationOfJoinRule::find_comparison_exprs (cognitive 16) src/frontend/src/optimizer/rule/push_calculation_of_join_rule.rs:137— PushCalculationOfJoinRule::find_comparison_exprs has cognitive complexity 16 (threshold 15). Drivers by points: if/else 7 (12 pts), boolean chains 3, loops 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TableFunctionToFileScanRule::apply (cognitive 16) src/frontend/src/optimizer/rule/table_function_to_file_scan_rule.rs:28— TableFunctionToFileScanRule::apply has cognitive complexity 16 (threshold 15). Drivers by points: if/else 7 (8 pts), match/switch 2 (6 pts), loops 1 (2 pts) (nesting depth added 6). To reduce it, split the body: this score is breadth rather than depth — many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages.
TopNToVectorSearchRule::resolve_vector_search (cognitive 16) src/frontend/src/optimizer/rule/top_n_to_vector_search_rule.rs:51— TopNToVectorSearchRule::resolve_vector_search has cognitive complexity 16 (threshold 15). Drivers by points: if/else 9 (12 pts), loops 2, boolean chains 1, match/switch 1 (nesting depth added 3). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
WithOptions::try_from (cognitive 16) src/frontend/src/utils/with_options.rs:539— WithOptions::try_from has cognitive complexity 16 (threshold 15). Drivers by points: if/else 3 (8 pts), match/switch 2 (4 pts), boolean chains 3, loops 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LoadedFragmentContext::into_database_contexts (cognitive 16) src/meta/src/controller/scale.rs:335— LoadedFragmentContext::into_database_contexts has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (12 pts), loops 3 (4 pts) (nesting depth added 8). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TierCompactionPicker::pick_overlapping_level (cognitive 16) src/meta/src/hummock/compaction/picker/tier_compaction_picker.rs:50— TierCompactionPicker::pick_overlapping_level has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (13 pts), loops 2 (3 pts) (nesting depth added 6). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
DynamicLevelSelectorCore::compact_pending_bytes_needed_with_ctx (cognitive 16) src/meta/src/hummock/compaction/selector/level_selector.rs:360— DynamicLevelSelectorCore::compact_pending_bytes_needed_with_ctx has cognitive complexity 16 (threshold 15). Drivers by points: if/else 7 (14 pts), boolean chains 1, loops 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MockHummockMetaClient::subscribe_compaction_event (cognitive 16) src/meta/src/hummock/mock_hummock_meta_client.rs:248— MockHummockMetaClient::subscribe_compaction_event has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (8 pts), match/switch 2 (5 pts), loops 2, boolean chains 1 (nesting depth added 7). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
TwoPhaseCommitHandler::next_to_commit (cognitive 16) src/meta/src/manager/sink_coordination/coordinator_worker.rs:165— TwoPhaseCommitHandler::next_to_commit has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (10 pts), loops 2 (4 pts), match/switch 1 (2 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
HummockVersionStateTableInfo::apply_delta (cognitive 16) src/storage/hummock_sdk/src/version.rs:101— HummockVersionStateTableInfo::apply_delta has cognitive complexity 16 (threshold 15). Drivers by points: if/else 6 (12 pts), loops 2, match/switch 1 (2 pts) (nesting depth added 7). Of this number, 15 points are the body's own statements and 1 belongs to one function item inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
CacheRefillTask::data_cache_refill (cognitive 16) src/storage/src/hummock/event_handler/refiller.rs:981— CacheRefillTask::data_cache_refill has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (10 pts), loops 3 (6 pts) (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
LogStoreRowSerde::deserialize_stream_chunk (cognitive 16) src/stream/src/common/log_store_impl/kv_log_store/serde.rs:437— LogStoreRowSerde::deserialize_stream_chunk has cognitive complexity 16 (threshold 15). Drivers by points: if/else 5 (13 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 9). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
StateTableBuilder::build_inner (cognitive 16) src/stream/src/common/table/state_table.rs:864— StateTableBuilder::build_inner has cognitive complexity 16 (threshold 15). Drivers by points: if/else 8 (10 pts), match/switch 3, boolean chains 2, loops 1 (nesting depth added 2). To reduce it, split the body: most of this score is breadth rather than depth — checks laid out side by side rather than stacked — so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level.
HashDataDispatcher::dispatch_data (cognitive 16) src/stream/src/executor/dispatch.rs:949— HashDataDispatcher::dispatch_data has cognitive complexity 16 (threshold 15). Drivers by points: if/else 7 (11 pts), loops 2 (3 pts), boolean chains 1, match/switch 1 (nesting depth added 5). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
ReadFuture::next_message (cognitive 16) src/stream/src/executor/sync_kv_log_store.rs:952— ReadFuture::next_message has cognitive complexity 16 (threshold 15). Drivers by points: match/switch 5 (9 pts), loops 2 (4 pts), if/else 1 (3 pts) (nesting depth added 8). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident.
TopNExecutorWrapper::top_n_executor_execute (cognitive 16) src/stream/src/executor/top_n/utils.rs:82— TopNExecutorWrapper::top_n_executor_execute has cognitive complexity 16 (threshold 15). Drivers by points: if/else 4 (13 pts), match/switch 1 (2 pts), loops 1 (nesting depth added 10). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body.
MongoDbValidator.validateUserPrivilege (cognitive 16) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MongoDbValidator.java:166— MongoDbValidator.validateUserPrivilege has cognitive complexity 16 (threshold 15). Drivers by points: if/else 6 (14 pts), error handling 1 (2 pts) (nesting depth added 9). To reduce it, flatten the nesting: this score is depth rather than breadth — most of its points come from checks stacked inside one another, so the work sits several levels in. Invert each enclosing check into an early exit (a return, or the language's equivalent) so the happy path stays at one level, and where a level cannot be exited early, lift the block it encloses into its own named function.
D22 · Internal API Consistency· Inconsistent access to metrics · ×1
Inconsistent access to metrics: `BatchTaskContext` provides a unified `batch_metrics()` method returning a composite `BatchMetrics` object, while `BatchEnvironment` exposes individual metric components (executor, manager, spill) as separate methods. This forces consumers to know whether they are interacting with a Task Context or an Environment to access metrics, and requires different code paths to get the same data. — Unify the interface by having `BatchEnvironment` also expose a `batch_metrics()` method that returns `BatchMetrics`, or ensure `BatchTaskContext` delegates to the same underlying source in a way that allows consistent access patterns across both types. (signatures: BatchTaskContext.batch_metrics(): BatchMetrics | BatchEnvironment.executor_metrics(): BatchExecutorMetrics | BatchEnvironment.batch_manager_metrics(): BatchManagerMetrics | BatchEnvironment.spill_metrics(): BatchSpillMetrics)
D22 · Internal API Consistency· Redundant/Confusing cancellation checks · ×1
Redundant/Confusing cancellation checks: `check()` returns a `Result` (likely checking for abort/cancel state), while `cancelled()` and `is_cancelled()` both appear to return boolean status. `cancelled()` and `is_cancelled()` are semantically identical, and `check()` overlaps in intent but differs in return type, creating confusion about which method to use for a simple boolean check. — Remove `cancelled()` and keep `is_cancelled(): bool` for simple checks. Keep `check()` only if it performs side effects or returns detailed error info; otherwise, unify to a single method with a clear return type. (signatures: ShutdownToken.check(): Result | ShutdownToken.cancelled() | ShutdownToken.is_cancelled(): bool)
D4 · Code Duplication· Near-duplicate member family (4 members, 15 shared lines) · ×1
Near-duplicate member family (4 members, 15 shared lines) src/frontend/src/handler/alter_rename.rs:76— src/frontend/src/handler/alter_rename.rs:76-101 | src/frontend/src/handler/alter_rename.rs:107-130 | src/frontend/src/handler/alter_rename.rs:136-160 | src/frontend/src/handler/alter_rename.rs:166-191 — These 4 members are variants of one another: a block of 15 lines reported below appears in every one of them, and the pairwise near-duplicate rows they would otherwise produce are collapsed into this row. Read them as one construct written 4 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 4 times.
D4 · Code Duplication· Near-duplicate member family (3 members, 29 shared lines) · ×1
Near-duplicate member family (3 members, 29 shared lines) src/storage/src/mem_table.rs:150— src/storage/src/mem_table.rs:150-202 | src/storage/src/mem_table.rs:204-283 | src/storage/src/mem_table.rs:290-370 — These 3 members are variants of one another: a block of 29 lines reported below appears in every one of them, and the pairwise near-duplicate rows they would otherwise produce are collapsed into this row. Read them as one construct written 3 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 3 times.
D4 · Code Duplication· Near-duplicate member family (3 members, 13 shared lines) · ×1
Near-duplicate member family (3 members, 13 shared lines) src/frontend/src/handler/create_aggregate.rs:35— src/frontend/src/handler/create_aggregate.rs:35-159 | src/frontend/src/handler/create_function.rs:52-216 | src/frontend/src/handler/create_sql_function.rs:34-186 — These 3 members are variants of one another: a block of 13 lines reported below appears in every one of them, and the pairwise near-duplicate rows they would otherwise produce are collapsed into this row. Read them as one construct written 3 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 3 times.
D4 · Code Duplication· Near-duplicate member family (3 members, 10 shared lines) · ×1
Near-duplicate member family (3 members, 10 shared lines) src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:217— src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:217-292 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:302-418 | src/frontend/src/optimizer/rule/apply_join_transpose_rule.rs:428-602 — These 3 members are variants of one another: a block of 10 lines reported below appears in every one of them, and the pairwise near-duplicate rows they would otherwise produce are collapsed into this row. Read them as one construct written 3 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 3 times.
Near-duplicate member pair (149 shared lines) src/stream/src/executor/asof_join.rs:323— src/stream/src/executor/asof_join.rs:323-505 | src/stream/src/executor/hash_join.rs:584-776 — These two members are variants of one another: 149 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (101 shared lines) src/stream/src/executor/nested_loop_temporal_join.rs:150— src/stream/src/executor/nested_loop_temporal_join.rs:150-293 | src/stream/src/executor/temporal_join.rs:666-877 — These two members are variants of one another: 101 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (85 shared lines) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:293— src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:293-388 | src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:861-976 — These two members are variants of one another: 85 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (71 shared lines) src/connector/src/sink/iceberg/writer.rs:330— src/connector/src/sink/iceberg/writer.rs:330-449 | src/connector/src/sink/iceberg/writer.rs:456-663 — These two members are variants of one another: 71 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (67 shared lines) src/stream/src/executor/eowc/eowc_gap_fill.rs:92— src/stream/src/executor/eowc/eowc_gap_fill.rs:92-266 | src/stream/src/executor/gap_fill.rs:279-471 — These two members are variants of one another: 67 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (58 shared lines) src/stream/src/common/table/state_table.rs:1956— src/stream/src/common/table/state_table.rs:1956-2036 | src/stream/src/common/table/state_table.rs:2044-2125 — These two members are variants of one another: 58 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (46 shared lines) src/frontend/src/metrics_reader.rs:51— src/frontend/src/metrics_reader.rs:51-188 | src/meta/src/dashboard/mod.rs:781-972 — These two members are variants of one another: 46 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (40 shared lines) src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:64— src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_all_files.rs:64-128 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_files.rs:63-121 — These two members are variants of one another: 40 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (37 shared lines) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_fetch.rs:75— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_fetch.rs:75-232 | src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:186-370 — These two members are variants of one another: 37 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (32 shared lines) src/stream/src/executor/top_n/group_top_n.rs:175— src/stream/src/executor/top_n/group_top_n.rs:175-245 | src/stream/src/executor/top_n/group_top_n_appendonly.rs:156-215 — These two members are variants of one another: 32 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
Near-duplicate member pair (28 shared lines) src/frontend/src/optimizer/plan_node/generic/join.rs:219— src/frontend/src/optimizer/plan_node/generic/join.rs:219-277 | src/frontend/src/optimizer/plan_node/stream_hash_join.rs:341-444 — These two members are variants of one another: 28 of their lines are already reported as duplicated blocks below, spread through both bodies rather than gathered into one. Read them as a single construct written twice. The repair is at the members' grain — factor the shared pipeline into one implementation the two call with their differences as parameters or as an injected step, or, where the difference is systematic (sync against async, one transport against another), generate one from the other. Extracting the individual blocks below is not the same fix: it leaves the two bodies in place and the next edit still has to be made twice.
D4 · Code Duplication· Edited copy of a member (34 corresponding lines) · ×1
Edited copy of a member (34 corresponding lines) src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:89— src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:89-133 | src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:140-202 — These two members are one piece of code written twice and then edited apart: 34 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Edited copy of a member (20 corresponding lines) · ×1
Edited copy of a member (20 corresponding lines) src/batch/executors/src/executor/aggregation/orderby.rs:128— src/batch/executors/src/executor/aggregation/orderby.rs:128-147 | src/frontend/src/datafusion/aggregate/orderby.rs:129-148 — These two members are one piece of code written twice and then edited apart: 20 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Edited copy of a member (31 corresponding lines) · ×1
Edited copy of a member (31 corresponding lines) src/stream/src/executor/dynamic_filter.rs:94— src/stream/src/executor/dynamic_filter.rs:94-211 | src/stream/src/executor/filter.rs:61-154 — These two members are one piece of code written twice and then edited apart: 31 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Edited copy of a member (19 corresponding lines) · ×1
Edited copy of a member (19 corresponding lines) src/frontend/src/optimizer/plan_node/batch_delete.rs:61— src/frontend/src/optimizer/plan_node/batch_delete.rs:61-79 | src/frontend/src/optimizer/plan_node/batch_insert.rs:73-91 — These two members are one piece of code written twice and then edited apart: 19 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Edited copy of a member (29 corresponding lines) · ×1
Edited copy of a member (29 corresponding lines) src/batch/executors/src/executor/join/hash_join.rs:2472— src/batch/executors/src/executor/join/hash_join.rs:2472-2513 | src/batch/executors/src/executor/join/nested_loop_join.rs:206-238 — These two members are one piece of code written twice and then edited apart: 29 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Edited copy of a member (13 corresponding lines) · ×1
Edited copy of a member (13 corresponding lines) src/connector/src/connector_common/iceberg/mod.rs:656— src/connector/src/connector_common/iceberg/mod.rs:656-715 | src/connector/src/connector_common/iceberg/mod.rs:717-763 — These two members are one piece of code written twice and then edited apart: 13 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Edited copy of a member (23 corresponding lines) · ×1
Edited copy of a member (23 corresponding lines) src/batch/executors/src/executor/hash_agg.rs:332— src/batch/executors/src/executor/hash_agg.rs:332-356 | src/batch/executors/src/executor/join/hash_join.rs:286-308 — These two members are one piece of code written twice and then edited apart: 23 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Members sharing a duplicated core (13 members, 50+ identical tokens) · ×1
Members sharing a duplicated core (13 members, 50+ identical tokens) REDACTED:279— REDACTED:279-292 | src/connector/src/sink/clickhouse.rs:380-393 | src/connector/src/sink/doris.rs:113-126 | src/connector/src/sink/file_sink/azblob.rs:110-123 | src/connector/src/sink/file_sink/fs.rs:80-92 | src/connector/src/sink/file_sink/gcs.rs:96-108 | src/connector/src/sink/file_sink/s3.rs:140-152 | src/connector/src/sink/file_sink/webhdfs.rs:84-97 | src/connector/src/sink/mongodb.rs:166-179 | src/connector/src/sink/postgres.rs:151-164 | src/connector/src/sink/snowflake_redshift/snowflake.rs:230-352 | src/connector/src/sink/sqlserver.rs:83-96 | src/connector/src/sink/starrocks.rs:156-179 — These 13 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 13 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 13 times.
D4 · Code Duplication· Members sharing a duplicated core (8 members, 50+ identical tokens) · ×1
Members sharing a duplicated core (8 members, 50+ identical tokens) src/batch/executors/src/executor/hash_agg.rs:383— src/batch/executors/src/executor/hash_agg.rs:383-396 | src/batch/executors/src/executor/hash_agg.rs:398-420 | src/batch/executors/src/executor/hash_agg.rs:422-454 | src/batch/executors/src/executor/join/hash_join.rs:341-363 | src/batch/executors/src/executor/join/hash_join.rs:369-391 | src/batch/executors/src/executor/join/hash_join.rs:393-425 | src/batch/executors/src/executor/order_by.rs:380-396 | src/batch/executors/src/executor/order_by.rs:398-416 — These 8 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 8 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 8 times.
D4 · Code Duplication· Members sharing a duplicated core (6 members, 50+ identical tokens) · ×1
Members sharing a duplicated core (6 members, 50+ identical tokens) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:91— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:91-201 | src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:74-226 | src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:163-271 | src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs:207-311 | src/stream/src/executor/source/fs_list_executor.rs:105-173 | src/stream/src/executor/source/iceberg_list_executor.rs:92-259 — These 6 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 6 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 6 times.
Duplicated block (101–104 lines × 2) src/stream/src/executor/asof_join.rs:324— src/stream/src/executor/asof_join.rs:324-424 | src/stream/src/executor/hash_join.rs:585-688 — before extracting anything, compare `src/stream/src/executor/asof_join.rs` and `src/stream/src/executor/hash_join.rs` as WHOLE FILES: this scan already matched 13 separate duplicated blocks between them, totalling at least 244 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (74–75 lines × 2) src/batch/executors/src/executor/join/distributed_lookup_join.rs:92— src/batch/executors/src/executor/join/distributed_lookup_join.rs:92-166 | src/batch/executors/src/executor/join/local_lookup_join.rs:294-367 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (53 lines × 2) src/connector/src/sink/coordinate.rs:160— src/connector/src/sink/coordinate.rs:160-212 | src/connector/src/sink/decouple_checkpoint_log_sink.rs:97-149 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (47 lines × 2) src/storage/hummock_sdk/src/compact_task.rs:297— src/storage/hummock_sdk/src/compact_task.rs:297-343 | src/storage/hummock_sdk/src/compact_task.rs:369-415 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (39 lines × 2) src/stream/src/executor/nested_loop_temporal_join.rs:220— src/stream/src/executor/nested_loop_temporal_join.rs:220-258 | src/stream/src/executor/temporal_join.rs:773-811 — before extracting anything, compare `src/stream/src/executor/nested_loop_temporal_join.rs` and `src/stream/src/executor/temporal_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 102 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (38 lines × 2) src/expr/impl/src/scalar/trigonometric.rs:258— src/expr/impl/src/scalar/trigonometric.rs:258-295 | src/expr/impl/src/scalar/trigonometric.rs:312-349 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (31–33 lines × 3) src/connector/src/source/kafka/stats.rs:582— src/connector/src/source/kafka/stats.rs:582-613 | src/meta/src/rpc/metrics.rs:999-1031 | src/storage/src/monitor/compactor_metrics.rs:275-305 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (30–32 lines × 2) src/connector/src/sink/iceberg/writer.rs:331— src/connector/src/sink/iceberg/writer.rs:331-360 | src/connector/src/sink/iceberg/writer.rs:457-488 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (31 lines × 3) src/storage/src/hummock/store/version.rs:707— src/storage/src/hummock/store/version.rs:707-737 | src/storage/src/hummock/store/version.rs:766-796 | src/storage/src/hummock/store/version.rs:832-862 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (31 lines × 2) src/meta/src/rpc/metrics.rs:1069— src/meta/src/rpc/metrics.rs:1069-1099 | src/stream/src/executor/monitor/streaming_stats.rs:1517-1547 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (29–30 lines × 2) src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs:61— src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs:61-89 | src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs:97-126 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (26–30 lines × 2) src/frontend/src/optimizer/plan_node/logical_join.rs:395— src/frontend/src/optimizer/plan_node/logical_join.rs:395-424 | src/frontend/src/optimizer/plan_node/logical_join.rs:1276-1301 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (28–29 lines × 2) src/frontend/src/handler/alter_owner.rs:196— src/frontend/src/handler/alter_owner.rs:196-223 | src/frontend/src/handler/alter_set_schema.rs:140-168 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (27–28 lines × 2) src/connector/src/parser/unified/debezium.rs:1242— src/connector/src/parser/unified/debezium.rs:1242-1268 | src/connector/src/parser/unified/debezium.rs:1315-1342 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (26–28 lines × 2) src/frontend/src/handler/create_aggregate.rs:93— src/frontend/src/handler/create_aggregate.rs:93-118 | src/frontend/src/handler/create_function.rs:143-170 — before extracting anything, compare `src/frontend/src/handler/create_aggregate.rs` and `src/frontend/src/handler/create_function.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 59 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (28 lines × 2) src/stream/src/executor/eowc/eowc_gap_fill.rs:160— src/stream/src/executor/eowc/eowc_gap_fill.rs:160-187 | src/stream/src/executor/gap_fill.rs:343-370 — before extracting anything, compare `src/stream/src/executor/eowc/eowc_gap_fill.rs` and `src/stream/src/executor/gap_fill.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 78 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (25–26 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:973— src/batch/executors/src/executor/join/hash_join.rs:973-998 | src/batch/executors/src/executor/join/hash_join.rs:1184-1208 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (24–26 lines × 2) src/frontend/src/optimizer/rule/apply_project_set_transpose_rule.rs:55— src/frontend/src/optimizer/rule/apply_project_set_transpose_rule.rs:55-80 | src/frontend/src/optimizer/rule/apply_project_transpose_rule.rs:51-74 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (23–26 lines × 2) src/stream/src/executor/eowc/eowc_gap_fill.rs:208— src/stream/src/executor/eowc/eowc_gap_fill.rs:208-230 | src/stream/src/executor/gap_fill.rs:399-424 — before extracting anything, compare `src/stream/src/executor/eowc/eowc_gap_fill.rs` and `src/stream/src/executor/gap_fill.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 78 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (24–25 lines × 2) src/stream/src/executor/top_n/top_n_cache.rs:508— src/stream/src/executor/top_n/top_n_cache.rs:508-531 | src/stream/src/executor/top_n/top_n_cache.rs:773-797 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (23–24 lines × 2) src/meta/model/migration/src/m20240701_060504_hummock_time_travel.rs:72— src/meta/model/migration/src/m20240701_060504_hummock_time_travel.rs:72-95 | src/meta/model/migration/src/m20240820_081248_add_time_travel_per_table_epoch.rs:161-183 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (17–23 lines × 2) src/frontend/src/optimizer/plan_node/batch_hash_join.rs:70— src/frontend/src/optimizer/plan_node/batch_hash_join.rs:70-86 | src/frontend/src/optimizer/plan_node/stream_join_common.rs:58-80 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (21–22 lines × 2) src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:93— src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:93-114 | src/frontend/src/optimizer/rule/min_max_on_index_rule.rs:164-184 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20–22 lines × 2) src/storage/src/hummock/iterator/skip_watermark.rs:361— src/storage/src/hummock/iterator/skip_watermark.rs:361-380 | src/storage/src/hummock/iterator/skip_watermark.rs:431-452 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20–21 lines × 3) src/batch/executors/src/executor/azblob_file_scan.rs:93— src/batch/executors/src/executor/azblob_file_scan.rs:93-113 | src/batch/executors/src/executor/gcs_file_scan.rs:82-101 | src/batch/executors/src/executor/s3_file_scan.rs:96-116 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 3 call sites, so a change lands once.
Duplicated block (16–21 lines × 2) src/storage/src/hummock/store/version.rs:1104— src/storage/src/hummock/store/version.rs:1104-1124 | src/storage/src/hummock/store/version.rs:1141-1156 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (20 lines × 3) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:126— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:126-145 | src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:148-167 | src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:206-225 — before extracting anything, compare `src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs` and `src/stream/src/executor/source/batch_source/batch_iceberg_list.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 89 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (19–20 lines × 2) src/batch/executors/src/executor/join/hash_join.rs:817— src/batch/executors/src/executor/join/hash_join.rs:817-836 | src/batch/executors/src/executor/join/hash_join.rs:909-927 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18–20 lines × 2) src/storage/src/hummock/local_version/pinned_version.rs:115— src/storage/src/hummock/local_version/pinned_version.rs:115-132 | src/storage/src/hummock/local_version/pinned_version.rs:137-156 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (10–19 lines × 2) src/stream/src/executor/source/source_backfill_executor.rs:237— src/stream/src/executor/source/source_backfill_executor.rs:237-255 | src/stream/src/executor/source/source_backfill_executor.rs:276-285 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (16–18 lines × 2) src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs:469— src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs:469-484 | src/meta/src/barrier/checkpoint/state.rs:229-246 — before extracting anything, compare `src/meta/src/barrier/checkpoint/independent_job/batch_refresh_job/mod.rs` and `src/meta/src/barrier/checkpoint/state.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 52 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (15–18 lines × 2) src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:492— src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:492-509 | src/stream/src/executor/backfill/cdc/cdc_backill_v2.rs:688-702 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12–17 lines × 3) src/connector/src/connector_common/iceberg/mod.rs:663— src/connector/src/connector_common/iceberg/mod.rs:663-674 | src/connector/src/connector_common/iceberg/mod.rs:730-741 | src/connector/src/connector_common/iceberg/mod.rs:786-802 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (11–17 lines × 2) src/cmd_all/src/standalone.rs:131— src/cmd_all/src/standalone.rs:131-141 | src/cmd_all/src/standalone.rs:145-161 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (14–16 lines × 3) src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:356— src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:356-369 | src/storage/hummock_sdk/src/compaction_group/hummock_version_ext.rs:944-957 | src/storage/hummock_sdk/src/compaction_group/mod.rs:323-338 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (13–16 lines × 2) src/frontend/src/optimizer/rule/pull_up_hop_rule.rs:72— src/frontend/src/optimizer/rule/pull_up_hop_rule.rs:72-84 | src/frontend/src/optimizer/rule/pull_up_hop_rule.rs:109-124 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (15 lines × 4) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:130— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:130-144 | src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:152-166 | src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:210-224 | src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs:249-263 — before extracting anything, compare `src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs` and `src/stream/src/executor/source/batch_source/batch_iceberg_list.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 89 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (13–14 lines × 3) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:112— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:112-124 | src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:109-121 | src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:188-201 — before extracting anything, compare `src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs` and `src/stream/src/executor/source/batch_source/batch_iceberg_list.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 89 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10–14 lines × 2) src/common/src/field_generator/numeric.rs:75— src/common/src/field_generator/numeric.rs:75-84 | src/common/src/field_generator/numeric.rs:117-130 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8–14 lines × 2) src/frontend/src/datafusion/aggregate/two_phase.rs:276— src/frontend/src/datafusion/aggregate/two_phase.rs:276-283 | src/frontend/src/datafusion/aggregate/two_phase.rs:323-336 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12–14 lines × 2) src/meta/src/controller/streaming_job.rs:2811— src/meta/src/controller/streaming_job.rs:2811-2822 | src/meta/src/controller/streaming_job.rs:3800-3813 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12–13 lines × 3) src/frontend/src/session.rs:1055— src/frontend/src/session.rs:1055-1067 | src/frontend/src/session.rs:1112-1123 | src/frontend/src/session.rs:1132-1144 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (10–13 lines × 3) src/meta/src/controller/catalog/alter_op.rs:51— src/meta/src/controller/catalog/alter_op.rs:51-60 | src/meta/src/controller/catalog/alter_op.rs:850-859 | src/meta/src/controller/catalog/alter_op.rs:882-894 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (9–13 lines × 2) src/stream/src/executor/join/asof_join.rs:602— src/stream/src/executor/join/asof_join.rs:602-610 | src/stream/src/executor/join/asof_join.rs:632-644 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (12 lines × 6) src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:92— src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs:92-103 | src/stream/src/executor/source/batch_source/batch_iceberg_list.rs:75-86 | src/stream/src/executor/source/batch_source/batch_opendal_fs_list.rs:164-175 | src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs:208-219 | src/stream/src/executor/source/fs_list_executor.rs:106-117 | src/stream/src/executor/source/iceberg_list_executor.rs:93-104 — before extracting anything, compare `src/stream/src/executor/source/batch_source/batch_adbc_snowflake_list.rs` and `src/stream/src/executor/source/batch_source/batch_iceberg_list.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 89 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11–12 lines × 5) src/frontend/src/catalog/system_catalog/rw_catalog/rw_internal_tables.rs:40— src/frontend/src/catalog/system_catalog/rw_catalog/rw_internal_tables.rs:40-51 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_sinks.rs:53-63 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_sources.rs:55-65 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_subscriptions.rs:41-52 | src/frontend/src/catalog/system_catalog/rw_catalog/rw_views.rs:37-47 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 5 call sites, so a change lands once.
Duplicated block (6–12 lines × 4) src/frontend/src/optimizer/plan_node/stream_dml.rs:36— src/frontend/src/optimizer/plan_node/stream_dml.rs:36-41 | src/frontend/src/optimizer/plan_node/stream_iceberg_with_pk_index_position_delete_merger.rs:50-55 | src/frontend/src/optimizer/plan_node/stream_sink.rs:216-227 | src/frontend/src/optimizer/plan_node/stream_sync_log_store.rs:40-45 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 4 call sites, so a change lands once.
Duplicated block (4–12 lines × 3) src/frontend/src/optimizer/plan_node/generic/filter.rs:70— src/frontend/src/optimizer/plan_node/generic/filter.rs:70-73 | src/frontend/src/optimizer/plan_node/generic/join.rs:405-416 | src/frontend/src/optimizer/plan_node/logical_multi_join.rs:274-285 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere all 3 call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made 3 times.
Duplicated block (11 lines × 11) REDACTED:282— REDACTED:282-292 | src/connector/src/sink/clickhouse.rs:383-393 | src/connector/src/sink/doris.rs:116-126 | src/connector/src/sink/file_sink/azblob.rs:113-123 | src/connector/src/sink/file_sink/fs.rs:82-92 | src/connector/src/sink/file_sink/gcs.rs:98-108 | src/connector/src/sink/file_sink/s3.rs:142-152 | src/connector/src/sink/file_sink/webhdfs.rs:87-97 | src/connector/src/sink/mongodb.rs:169-179 | src/connector/src/sink/postgres.rs:154-164 | src/connector/src/sink/sqlserver.rs:86-96 — before extracting anything, compare `src/connector/src/sink/doris.rs` and `src/connector/src/sink/sqlserver.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 36 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (9–11 lines × 3) src/stream/src/executor/backfill/arrangement_backfill.rs:341— src/stream/src/executor/backfill/arrangement_backfill.rs:341-349 | src/stream/src/executor/backfill/arrangement_backfill.rs:394-402 | REDACTED:656-666 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (7–11 lines × 2) src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:161— src/stream/src/executor/source/batch_source/batch_opendal_fs_fetch.rs:161-167 | src/stream/src/executor/source/fs_fetch_executor.rs:210-220 — the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach — a location they all depend on today, or a new shared one if there is none — and call it from each site; until then, every change has to be made twice.
Duplicated block (8–10 lines × 5) src/meta/src/hummock/mod.rs:102— src/meta/src/hummock/mod.rs:102-109 | src/meta/src/hummock/mod.rs:136-145 | src/meta/src/hummock/mod.rs:163-172 | src/meta/src/hummock/mod.rs:200-209 | src/meta/src/rpc/metrics.rs:1134-1143 — there are 5 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 5 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (9–10 lines × 3) src/batch/executors/src/executor/join/hash_join.rs:979— src/batch/executors/src/executor/join/hash_join.rs:979-988 | src/batch/executors/src/executor/join/hash_join.rs:1190-1198 | src/batch/executors/src/executor/join/hash_join.rs:1597-1605 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (9 lines × 13) REDACTED:282— REDACTED:282-290 | src/connector/src/sink/clickhouse.rs:383-391 | src/connector/src/sink/doris.rs:116-124 | src/connector/src/sink/file_sink/azblob.rs:113-121 | src/connector/src/sink/file_sink/fs.rs:82-90 | src/connector/src/sink/file_sink/gcs.rs:98-106 | src/connector/src/sink/file_sink/s3.rs:142-150 | src/connector/src/sink/file_sink/webhdfs.rs:87-95 | src/connector/src/sink/mongodb.rs:169-177 | src/connector/src/sink/postgres.rs:154-162 | src/connector/src/sink/snowflake_redshift/snowflake.rs:233-241 | src/connector/src/sink/sqlserver.rs:86-94 | src/connector/src/sink/starrocks.rs:159-167 — before extracting anything, compare `src/connector/src/sink/doris.rs` and `src/connector/src/sink/sqlserver.rs` as WHOLE FILES: this scan already matched 4 separate duplicated blocks between them, totalling at least 36 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (9 lines × 11) src/batch/executors/src/executor/join/hash_join.rs:792— src/batch/executors/src/executor/join/hash_join.rs:792-800 | src/batch/executors/src/executor/join/hash_join.rs:873-881 | src/batch/executors/src/executor/join/hash_join.rs:970-978 | src/batch/executors/src/executor/join/hash_join.rs:1048-1056 | src/batch/executors/src/executor/join/hash_join.rs:1108-1116 | src/batch/executors/src/executor/join/hash_join.rs:1181-1189 | src/batch/executors/src/executor/join/hash_join.rs:1259-1267 | src/batch/executors/src/executor/join/hash_join.rs:1321-1329 | src/batch/executors/src/executor/join/hash_join.rs:1438-1446 | src/batch/executors/src/executor/join/hash_join.rs:1508-1516 | src/batch/executors/src/executor/join/hash_join.rs:1587-1595 — all 11 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (9 lines × 5) src/frontend/src/optimizer/plan_node/generic/file_scan.rs:111— src/frontend/src/optimizer/plan_node/generic/file_scan.rs:111-119 | src/frontend/src/optimizer/plan_node/generic/file_scan.rs:158-166 | src/frontend/src/optimizer/plan_node/generic/file_scan.rs:171-179 | src/frontend/src/optimizer/plan_node/generic/mysql_query.rs:58-66 | src/frontend/src/optimizer/plan_node/generic/postgres_query.rs:60-68 — there are 5 copies across 3 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 5 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (8–9 lines × 5) src/frontend/src/handler/alter_owner.rs:92— src/frontend/src/handler/alter_owner.rs:92-100 | src/frontend/src/handler/alter_owner.rs:107-114 | src/frontend/src/handler/alter_owner.rs:121-128 | src/frontend/src/handler/alter_owner.rs:137-145 | src/frontend/src/handler/alter_owner.rs:154-162 — all 5 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (8 lines × 9) src/frontend/src/handler/handle_privilege.rs:79— src/frontend/src/handler/handle_privilege.rs:79-86 | src/frontend/src/handler/handle_privilege.rs:103-110 | src/frontend/src/handler/handle_privilege.rs:140-147 | src/frontend/src/handler/handle_privilege.rs:154-161 | src/frontend/src/handler/handle_privilege.rs:169-176 | src/frontend/src/handler/handle_privilege.rs:183-190 | src/frontend/src/handler/handle_privilege.rs:197-204 | src/frontend/src/handler/handle_privilege.rs:210-217 | src/frontend/src/handler/handle_privilege.rs:255-262 — all 9 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (1–8 lines × 3) src/common/src/array/arrow/arrow_impl.rs:260— src/common/src/array/arrow/arrow_impl.rs:260-267 | src/common/src/array/arrow/arrow_impl.rs:285-292 | src/common/src/array/arrow/arrow_impl.rs:336-336 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (7–8 lines × 2) src/meta/src/controller/catalog/alter_op.rs:116— src/meta/src/controller/catalog/alter_op.rs:116-122 | src/meta/src/controller/catalog/drop_op.rs:32-39 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (6–7 lines × 14) src/frontend/src/handler/alter_connection_props.rs:31— src/frontend/src/handler/alter_connection_props.rs:31-36 | src/frontend/src/handler/alter_mv.rs:41-47 | src/frontend/src/handler/alter_rename.rs:38-44 | src/frontend/src/handler/alter_rename.rs:82-88 | src/frontend/src/handler/alter_rename.rs:112-118 | src/frontend/src/handler/alter_rename.rs:141-147 | src/frontend/src/handler/alter_rename.rs:172-178 | src/frontend/src/handler/alter_rename.rs:203-209 | src/frontend/src/handler/alter_source_props.rs:37-42 | src/frontend/src/handler/alter_source_props.rs:141-146 | src/frontend/src/handler/alter_subscription_retention.rs:91-96 | src/frontend/src/handler/drop_index.rs:39-44 | src/frontend/src/handler/drop_mv.rs:36-42 | src/frontend/src/handler/drop_view.rs:33-39 — there are 14 copies across 8 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 14 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (5–7 lines × 2) src/connector/src/source/cdc/external/mysql.rs:896— src/connector/src/source/cdc/external/mysql.rs:896-902 | REDACTED:431-435 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from both call sites, so a change lands once.
Duplicated block (5–6 lines × 11) src/frontend/src/handler/alter_connection_props.rs:27— src/frontend/src/handler/alter_connection_props.rs:27-32 | src/frontend/src/handler/alter_set_schema.rs:37-41 | src/frontend/src/handler/alter_source_props.rs:33-38 | src/frontend/src/handler/alter_source_props.rs:137-142 | src/frontend/src/handler/alter_subscription_retention.rs:87-92 | src/frontend/src/handler/alter_swap_rename.rs:53-58 | src/frontend/src/handler/drop_connection.rs:32-37 | src/frontend/src/handler/drop_index.rs:36-40 | src/frontend/src/handler/drop_mv.rs:33-37 | src/frontend/src/handler/drop_subscription.rs:30-35 | src/frontend/src/handler/drop_view.rs:30-34 — there are 11 copies across 10 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 11 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (6 lines × 10) src/batch/executors/src/executor/hash_agg.rs:386— src/batch/executors/src/executor/hash_agg.rs:386-391 | src/batch/executors/src/executor/hash_agg.rs:409-414 | src/batch/executors/src/executor/hash_agg.rs:425-430 | src/batch/executors/src/executor/hash_agg.rs:436-441 | src/batch/executors/src/executor/join/hash_join.rs:352-357 | src/batch/executors/src/executor/join/hash_join.rs:380-385 | src/batch/executors/src/executor/join/hash_join.rs:396-401 | src/batch/executors/src/executor/join/hash_join.rs:407-412 | src/batch/executors/src/executor/order_by.rs:384-389 | src/batch/executors/src/executor/order_by.rs:401-406 — before extracting anything, compare `src/batch/executors/src/executor/hash_agg.rs` and `src/batch/executors/src/executor/join/hash_join.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 81 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (5–6 lines × 9) src/frontend/src/handler/alter_connection_props.rs:30— src/frontend/src/handler/alter_connection_props.rs:30-35 | src/frontend/src/handler/alter_source_props.rs:36-41 | src/frontend/src/handler/alter_source_props.rs:140-145 | src/frontend/src/handler/alter_subscription_retention.rs:90-95 | src/frontend/src/handler/drop_index.rs:39-43 | src/frontend/src/handler/drop_mv.rs:36-41 | src/frontend/src/handler/drop_sink.rs:35-39 | src/frontend/src/handler/drop_subscription.rs:33-38 | src/frontend/src/handler/drop_view.rs:33-38 — there are 9 copies across 8 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 9 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (4–6 lines × 6) src/frontend/src/handler/alter_mv.rs:40— src/frontend/src/handler/alter_mv.rs:40-44 | src/frontend/src/handler/alter_source_with_sr.rs:105-109 | src/frontend/src/handler/alter_table_column.rs:326-331 | src/frontend/src/handler/alter_utils.rs:63-66 | src/frontend/src/handler/drop_secret.rs:65-69 | src/frontend/src/handler/util.rs:330-335 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 6 call sites, so a change lands once.
Duplicated block (4–5 lines × 3) src/common/src/array/arrow/arrow_iceberg.rs:146— src/common/src/array/arrow/arrow_iceberg.rs:146-150 | src/common/src/array/arrow/arrow_iceberg.rs:518-521 | src/common/src/array/arrow/arrow_impl.rs:382-386 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (5 lines × 11) src/frontend/src/optimizer/plan_node/batch_filter.rs:101— src/frontend/src/optimizer/plan_node/batch_filter.rs:101-105 | src/frontend/src/optimizer/plan_node/batch_hash_agg.rs:164-168 | src/frontend/src/optimizer/plan_node/batch_nested_loop_join.rs:140-144 | src/frontend/src/optimizer/plan_node/batch_project.rs:115-119 | src/frontend/src/optimizer/plan_node/batch_project_set.rs:98-102 | src/frontend/src/optimizer/plan_node/batch_simple_agg.rs:153-157 | src/frontend/src/optimizer/plan_node/batch_table_function.rs:77-81 | src/frontend/src/optimizer/plan_node/batch_values.rs:101-105 | src/frontend/src/optimizer/plan_node/stream_filter.rs:118-122 | src/frontend/src/optimizer/plan_node/stream_project_set.rs:149-153 | src/frontend/src/optimizer/plan_node/stream_values.rs:89-93 — the copies sit in sibling files of one directory, so a shared home is within easy reach: extract the block into a single shared function the call sites can all reach — a file they already depend on, or a new one alongside them — and call it from all 11 call sites, so a change lands once.
Duplicated block (9 lines × 9) src/frontend/src/optimizer/plan_node/logical_agg.rs:1231— src/frontend/src/optimizer/plan_node/logical_agg.rs:1231-1239 | src/frontend/src/optimizer/plan_node/logical_filter.rs:168-176 | src/frontend/src/optimizer/plan_node/logical_join.rs:720-728 | src/frontend/src/optimizer/plan_node/logical_project.rs:179-187 | src/frontend/src/optimizer/plan_node/logical_project_set.rs:302-310 | src/frontend/src/optimizer/plan_node/logical_scan.rs:457-465 | src/frontend/src/optimizer/plan_node/stream_eowc_gap_fill.rs:195-203 | src/frontend/src/optimizer/plan_node/stream_gap_fill.rs:193-201 | src/frontend/src/optimizer/plan_node/stream_match_recognize.rs:278-286 — before extracting anything, compare `src/frontend/src/optimizer/plan_node/logical_project.rs` and `src/frontend/src/optimizer/plan_node/logical_project_set.rs` as WHOLE FILES: this scan already matched 5 separate duplicated blocks between them, totalling at least 62 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (14 lines × 4) src/risedevtool/src/task/compactor_service.rs:89— src/risedevtool/src/task/compactor_service.rs:89-102 | src/risedevtool/src/task/compute_node_service.rs:111-124 | src/risedevtool/src/task/frontend_service.rs:102-115 | src/risedevtool/src/task/meta_node_service.rs:274-287 — before extracting anything, compare `src/risedevtool/src/task/compactor_service.rs` and `src/risedevtool/src/task/compute_node_service.rs` as WHOLE FILES: this scan already matched 3 separate duplicated blocks between them, totalling at least 30 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (7 lines × 5) src/meta/src/controller/utils.rs:941— src/meta/src/controller/utils.rs:941-950 | src/meta/src/controller/utils.rs:960-966 | src/meta/src/controller/utils.rs:976-982 | src/meta/src/controller/utils.rs:1013-1019 | src/meta/src/controller/utils.rs:1029-1035 — all 5 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (7 lines × 12) src/sqlparser/src/parser.rs:3388— src/sqlparser/src/parser.rs:3388-3396 | src/sqlparser/src/parser.rs:3403-3411 | src/sqlparser/src/parser.rs:3554-3562 | src/sqlparser/src/parser.rs:3569-3577 | src/sqlparser/src/parser.rs:3584-3590 | src/sqlparser/src/parser.rs:3664-3672 | src/sqlparser/src/parser.rs:3696-3703 | src/sqlparser/src/parser.rs:3772-3779 | src/sqlparser/src/parser.rs:3786-3793 | src/sqlparser/src/parser.rs:3800-3806 | src/sqlparser/src/parser.rs:3929-3936 | src/sqlparser/src/parser.rs:3943-3950 — all 12 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (5 lines × 7) src/risedevtool/src/bin/risedev-dev.rs:187— src/risedevtool/src/bin/risedev-dev.rs:187-192 | src/risedevtool/src/bin/risedev-dev.rs:207-212 | src/risedevtool/src/bin/risedev-dev.rs:216-221 | src/risedevtool/src/bin/risedev-dev.rs:252-257 | src/risedevtool/src/bin/risedev-dev.rs:378-383 | src/risedevtool/src/bin/risedev-dev.rs:386-391 | src/risedevtool/src/bin/risedev-dev.rs:404-408 — all 7 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (24–30 lines × 2) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/DbzConnectorConfig.java:198— java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/DbzConnectorConfig.java:198-227 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/DbzConnectorConfig.java:362-385 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/DbzConnectorConfig.java:198` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (22–23 lines × 2) java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java:238— java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java:238-260 | java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java:285-306 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (8–10 lines × 3) java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:112— java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:112-121 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:123-132 | java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:133-140 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. Read the line range as the matched WINDOW rather than a finished unit: at `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:112` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names — the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just before the matched lines, `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:108` calls `validateBinlogConfig` and `java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/MySqlValidator.java:118` does not — after which the two agree again for 2 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
D4 · Code Duplication· Near-duplicate member family (3 members, 66 shared lines) · ×1
Near-duplicate member family (3 members, 66 shared lines) integration_tests/feature-store/server/src/model.rs:250— integration_tests/feature-store/server/src/model.rs:250-354 | integration_tests/feature-store/server/src/server_pb.rs:429-673 | integration_tests/feature-store/simulator/src/server_pb.rs:429-673 — These 3 members are variants of one another: a block of 66 lines reported below appears in every one of them, and the pairwise near-duplicate rows they would otherwise produce are collapsed into this row. Read them as one construct written 3 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 3 times.
D4 · Code Duplication· Edited copy of a member (32 corresponding lines) · ×1
Edited copy of a member (32 corresponding lines) REDACTED:449— REDACTED:449-480 | REDACTED:483-514 — These two members are one piece of code written twice and then edited apart: 32 consecutive lines correspond almost exactly, broken only by small local edits. Most of that correspondence is NOT reported as duplicated blocks below — the edits cut it into fragments and only the largest of them clear the block floor, so the rows below understate it. The repair is at the members' grain — factor the shared implementation into one the two call with their differences as parameters or as an injected step, or, where the difference is systematic (an extra return value, one transport against another), generate one from the other. Left alone, the next edit has to be made twice and the two will drift further apart.
D4 · Code Duplication· Members sharing a duplicated core (12 members, 50+ identical tokens) · ×1
Members sharing a duplicated core (12 members, 50+ identical tokens) integration_tests/feature-store/server/src/model.rs:112— integration_tests/feature-store/server/src/model.rs:112-127 | integration_tests/feature-store/server/src/model.rs:134-149 | integration_tests/feature-store/server/src/server_pb.rs:189-207 | integration_tests/feature-store/server/src/server_pb.rs:214-232 | integration_tests/feature-store/server/src/server_pb.rs:239-257 | integration_tests/feature-store/server/src/server_pb.rs:264-282 | integration_tests/feature-store/server/src/server_pb.rs:289-307 | integration_tests/feature-store/simulator/src/server_pb.rs:189-207 | integration_tests/feature-store/simulator/src/server_pb.rs:214-232 | integration_tests/feature-store/simulator/src/server_pb.rs:239-257 | integration_tests/feature-store/simulator/src/server_pb.rs:264-282 | integration_tests/feature-store/simulator/src/server_pb.rs:289-307 — These 12 members share a duplicated core: a run of at least 50 identical tokens appears in every one of them. That run is NOT broken out as duplicated-block rows below — it is what admitted this row, and the blocks below cover only the part of it that clears the block floor, so they understate the correspondence. Read the members as one construct written 12 times. The repair is at the members' grain — factor the shared implementation out once and have all of them call it with their differences as parameters or as an injected step, or, where the difference is systematic, generate them from one template. Extracting the individual blocks below is not the same fix: it leaves every body in place and the next edit still has to be made 12 times.
Duplicated block (225 lines × 2) integration_tests/feature-store/server/src/server_pb.rs:430— integration_tests/feature-store/server/src/server_pb.rs:430-654 | integration_tests/feature-store/simulator/src/server_pb.rs:430-654 — before extracting anything, compare `integration_tests/feature-store/server/src/server_pb.rs` and `integration_tests/feature-store/simulator/src/server_pb.rs` as WHOLE FILES: this scan already matched 12 separate duplicated blocks between them, totalling at least 380 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. The two sit in different directories, so one cannot simply be deleted in favour of the other while both are reached separately: hoist the shared part into a location both already depend on and have each file call it, and retire whichever file turns out to have no caller of its own left. Extracting one helper per block leaves the fork in place.
Duplicated block (28 lines × 3) integration_tests/feature-store/server/src/model.rs:327— integration_tests/feature-store/server/src/model.rs:327-354 | integration_tests/feature-store/server/src/server_pb.rs:646-673 | integration_tests/feature-store/simulator/src/server_pb.rs:646-673 — before extracting anything, compare `integration_tests/feature-store/server/src/model.rs` and `integration_tests/feature-store/server/src/server_pb.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 85 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (15 lines × 12) integration_tests/feature-store/server/src/model.rs:282— integration_tests/feature-store/server/src/model.rs:282-296 | integration_tests/feature-store/server/src/model.rs:326-340 | integration_tests/feature-store/server/src/server_pb.rs:461-475 | integration_tests/feature-store/server/src/server_pb.rs:507-521 | integration_tests/feature-store/server/src/server_pb.rs:553-567 | integration_tests/feature-store/server/src/server_pb.rs:599-613 | integration_tests/feature-store/server/src/server_pb.rs:645-659 | integration_tests/feature-store/simulator/src/server_pb.rs:461-475 | integration_tests/feature-store/simulator/src/server_pb.rs:507-521 | integration_tests/feature-store/simulator/src/server_pb.rs:553-567 | integration_tests/feature-store/simulator/src/server_pb.rs:599-613 | integration_tests/feature-store/simulator/src/server_pb.rs:645-659 — before extracting anything, compare `integration_tests/feature-store/server/src/model.rs` and `integration_tests/feature-store/server/src/server_pb.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 85 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (10–11 lines × 12) integration_tests/feature-store/server/src/model.rs:113— integration_tests/feature-store/server/src/model.rs:113-122 | integration_tests/feature-store/server/src/model.rs:135-144 | integration_tests/feature-store/server/src/server_pb.rs:190-200 | integration_tests/feature-store/server/src/server_pb.rs:215-225 | integration_tests/feature-store/server/src/server_pb.rs:240-250 | integration_tests/feature-store/server/src/server_pb.rs:265-275 | integration_tests/feature-store/server/src/server_pb.rs:290-300 | integration_tests/feature-store/simulator/src/server_pb.rs:190-200 | integration_tests/feature-store/simulator/src/server_pb.rs:215-225 | integration_tests/feature-store/simulator/src/server_pb.rs:240-250 | integration_tests/feature-store/simulator/src/server_pb.rs:265-275 | integration_tests/feature-store/simulator/src/server_pb.rs:290-300 — before extracting anything, compare `integration_tests/feature-store/server/src/model.rs` and `integration_tests/feature-store/server/src/server_pb.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 85 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (11 lines × 12) integration_tests/feature-store/server/src/model.rs:270— integration_tests/feature-store/server/src/model.rs:270-280 | integration_tests/feature-store/server/src/model.rs:314-324 | integration_tests/feature-store/server/src/server_pb.rs:449-459 | integration_tests/feature-store/server/src/server_pb.rs:495-505 | integration_tests/feature-store/server/src/server_pb.rs:541-551 | integration_tests/feature-store/server/src/server_pb.rs:587-597 | integration_tests/feature-store/server/src/server_pb.rs:633-643 | integration_tests/feature-store/simulator/src/server_pb.rs:449-459 | integration_tests/feature-store/simulator/src/server_pb.rs:495-505 | integration_tests/feature-store/simulator/src/server_pb.rs:541-551 | integration_tests/feature-store/simulator/src/server_pb.rs:587-597 | integration_tests/feature-store/simulator/src/server_pb.rs:633-643 — before extracting anything, compare `integration_tests/feature-store/server/src/model.rs` and `integration_tests/feature-store/server/src/server_pb.rs` as WHOLE FILES: this scan already matched 6 separate duplicated blocks between them, totalling at least 85 lines, which is the signature of one file having been copied from the other rather than of a helper waiting to be extracted. If that is what happened, the fix is to keep one copy and have the other call it (or delete it), which resolves this row and its siblings together — extracting one helper per block leaves the fork in place.
Duplicated block (90 lines × 2) e2e_test/s3/file_sink.py:173— e2e_test/s3/file_sink.py:173-262 | e2e_test/s3/file_sink.py:266-355 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at `e2e_test/s3/file_sink.py:173` it does not close everything it opens, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (38–42 lines × 2) e2e_test/s3/file_source.py:70— e2e_test/s3/file_source.py:70-111 | e2e_test/s3/file_source.py:249-286 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it.
Duplicated block (34–40 lines × 3) e2e_test/s3/file_source.py:59— e2e_test/s3/file_source.py:59-94 | e2e_test/s3/file_source.py:160-199 | e2e_test/s3/file_source.py:239-272 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. Read the line range as the matched WINDOW rather than a finished unit: at `e2e_test/s3/file_source.py:239` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names — the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately.
Duplicated block (10–30 lines × 4) e2e_test/webhook/websocket_sender.py:456— e2e_test/webhook/websocket_sender.py:456-465 | e2e_test/webhook/websocket_sender.py:481-510 | e2e_test/webhook/websocket_sender.py:514-543 | e2e_test/webhook/websocket_sender.py:547-574 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. Read the line range as the matched WINDOW rather than a finished unit: at `e2e_test/webhook/websocket_sender.py:456` it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand — widen the region to the smallest complete statement or declaration that contains it, and extract that.
Duplicated block (18–23 lines × 2) e2e_test/s3/file_source.py:20— e2e_test/s3/file_source.py:20-37 | e2e_test/s3/file_source.py:124-146 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (11–22 lines × 3) integration_tests/iceberg-sink2/python/main.py:39— integration_tests/iceberg-sink2/python/main.py:39-60 | integration_tests/iceberg-sink2/python/main.py:116-126 | integration_tests/iceberg-source/python/main.py:41-62 — there are 3 copies across 2 file(s) — more copies than files, so at least one file holds the block twice. Extract it once into a single shared function every call site can reach and call it from all 3 sites; resolving a subset leaves the remainder to drift apart.
Duplicated block (14–15 lines × 4) REDACTED:96— REDACTED:96-110 | REDACTED:174-188 | REDACTED:296-310 | REDACTED:548-561 — all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Duplicated block (13–14 lines × 8) REDACTED:95— REDACTED:95-108 | REDACTED:123-136 | REDACTED:148-161 | REDACTED:173-186 | REDACTED:295-308 | REDACTED:338-351 | REDACTED:360-372 | REDACTED:547-559 — all 8 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited. ★ These copies have DRIFTED, and that is worth reading before extracting anything: just after the matched lines, `REDACTED:137` calls `sleep` and `REDACTED:109` does not — after which the two agree again for 4 more lines. One of those two behaviours is the intended one and the other is what a copy-paste left behind, so decide which BEFORE unifying them: extracting the shared part will silently settle it, and if the copy that skips the call is the wrong one, that bug is already live.
Duplicated block (11–14 lines × 3) REDACTED:81— REDACTED:81-91 | REDACTED:107-119 | REDACTED:238-251 — all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites — resolving only two of them leaves the rest to drift apart the first time one is edited.
Coverage not measured — .NET and JavaScript/TypeScript suite — Coverage NOT MEASURED: the .NET half could not be measured — no coverage produced (collector absent, or test run exceeded the inline budget); the JavaScript/TypeScript half could not be measured — the jest suite in src/utils/pgwire/tests/js/ ran and not one test passed (FAIL test/pgwire.test.ts), so the coverage would describe the failed run, not the code. This repository's production source spans both ecosystems, and no partial figure is published as if it were the whole: coverage is excluded from the score rather than counted as a near-zero. The named suite step is one the repository's maintainers can perform; once it passes, the real number is measured on the next scan. Alternatively, commit the lcov/Cobertura report your CI produces and it is read without a re-run.
DM7 · Repository granularity· Repository for a non-root entity · ×1
Repository for a non-root entity: SpringTestRepository → SpringTest integration_tests/client-library/spring-boot/src/main/java/com/risingwave/SpringTestRepository.java:8— `SpringTestRepository` is a repository over `SpringTest`, which is an entity but not an aggregate root. Repositories should be per aggregate ROOT — loading/saving a child entity independently lets callers bypass the root's invariants. Access `SpringTest` through its owning aggregate instead.
P3 · Security & performance tooling· SAST runs, but gates no merge · ×1
SAST runs, but gates no merge — `REDACTED` run(s) a static-analysis scan, but no workflow that runs one is triggered by a pull request (or a merge queue, or an unfiltered push) — the scan fires on a schedule or a manual dispatch only. A vulnerable change therefore merges clean and is reported on the next scheduled run, by which time it is on the default branch and the only remedy is a follow-up fix. Add the pull-request trigger to the workflow that runs the scan so the finding arrives before the merge rather than after it.
R10 · Code Duplication· Duplicated block with local edits (105 matched lines × 2 locations) · ×1
Duplicated block with local edits (105 matched lines × 2 locations) dashboard/pages/cpu_profiling.tsx:41— dashboard/pages/cpu_profiling.tsx:41 · dashboard/pages/heap_profiling.tsx:48 — the two spans are one implementation copied and then locally edited — 621 tokens are still identical, in the same order in both files, with only local edits between them. The copies have already begun to drift, which is this row's finding: an edit made to one and not the other changes behaviour silently. Diff the two spans first to learn what genuinely differs, then extract the shared core into one module both sites use, passing the differences in as parameters — or, if one copy exists only because the other could not be imported from its context, make one of them the single source the other is generated or re-exported from. If one copy is no longer reachable, delete it rather than letting it shadow the live one.
R10 · Code Duplication· Duplicated block with local edits (76 matched lines × 2 locations) · ×1
Duplicated block with local edits (76 matched lines × 2 locations) dashboard/pages/fragment_graph.tsx:337— dashboard/pages/fragment_graph.tsx:337 · dashboard/pages/relation_graph.tsx:93 — the two spans are one implementation copied and then locally edited — 329 tokens are still identical, in the same order in both files, with only local edits between them. The copies have already begun to drift, which is this row's finding: an edit made to one and not the other changes behaviour silently. Diff the two spans first to learn what genuinely differs, then extract the shared core into one module both sites use, passing the differences in as parameters — or, if one copy exists only because the other could not be imported from its context, make one of them the single source the other is generated or re-exported from. If one copy is no longer reachable, delete it rather than letting it shadow the live one.
Duplicated block (42 lines × 2 locations) dashboard/pages/await_tree.tsx:133— dashboard/pages/await_tree.tsx:133 · dashboard/pages/heap_profiling.tsx:277 — the 2 copies are spread across 2 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
Duplicated block (29 lines × 2 locations) dashboard/components/FragmentGraph.tsx:529— dashboard/components/FragmentGraph.tsx:529 · dashboard/components/RelationGraph.tsx:221 — the 2 copies sit in sibling files in one directory, so check first whether one of them (or an existing module there) already owns this behaviour and the others should call it; otherwise extract it into one module in that directory and have each site call it.
Duplicated block (22 lines × 4 locations) dashboard/components/FragmentGraph.tsx:328— dashboard/components/FragmentGraph.tsx:328 · dashboard/components/FragmentGraph.tsx:533 · dashboard/components/RelationGraph.tsx:223 · dashboard/components/RelationGraph.tsx:380 — the 2 copies sit in sibling files in one directory, so check first whether one of them (or an existing module there) already owns this behaviour and the others should call it; otherwise extract it into one module in that directory and have each site call it.
Duplicated block (20 lines × 2 locations) dashboard/lib/api/streamingStats.ts:83— dashboard/lib/api/streamingStats.ts:83 · dashboard/lib/api/streamingStats.ts:118 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (18 lines × 2 locations) dashboard/components/utils/stroke-icons.tsx:124— dashboard/components/utils/stroke-icons.tsx:124 · dashboard/components/utils/stroke-icons.tsx:233 — all 2 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
Duplicated block (16 lines × 2 locations) dashboard/pages/cluster.tsx:293— dashboard/pages/cluster.tsx:293 · dashboard/pages/cluster.tsx:309 — all 2 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
R10 · Code Duplication· Duplicated block with local edits (14 matched lines × 2 locations) · ×1
Duplicated block with local edits (14 matched lines × 2 locations) dashboard/lib/algo.ts:31— dashboard/lib/algo.ts:31 · dashboard/lib/algo.ts:52 — the two spans are one implementation copied and then locally edited — 63 tokens are still identical, in the same order in both spans, with only local edits between them. The copies have already begun to drift, which is this row's finding: an edit made to one and not the other changes behaviour silently. Diff the two spans first to learn what genuinely differs, then extract the shared core into one module both sites use, passing the differences in as parameters — or, if one copy exists only because the other could not be imported from its context, make one of them the single source the other is generated or re-exported from. If one copy is no longer reachable, delete it rather than letting it shadow the live one.
Duplicated block (13 lines × 2 locations) dashboard/components/FragmentGraph.tsx:246— dashboard/components/FragmentGraph.tsx:246 · dashboard/components/FragmentGraph.tsx:262 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Duplicated block (13 lines × 3 locations) dashboard/pages/await_tree.tsx:103— dashboard/pages/await_tree.tsx:103 · dashboard/pages/fragment_graph.tsx:372 · dashboard/pages/heap_profiling.tsx:204 — the 3 copies are spread across 3 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
Duplicated block (12 lines × 2 locations) dashboard/components/FragmentDependencyGraph.tsx:159— dashboard/components/FragmentDependencyGraph.tsx:159 · dashboard/components/FragmentDependencyGraph.tsx:171 — all 2 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
Duplicated block (11 lines × 2 locations) dashboard/components/FragmentGraph.tsx:188— dashboard/components/FragmentGraph.tsx:188 · dashboard/components/RelationGraph.tsx:127 — the 2 copies are spread across 2 files, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
Duplicated block (8 lines × 3 locations) dashboard/pages/await_tree.tsx:71— dashboard/pages/await_tree.tsx:71 · dashboard/pages/await_tree.tsx:80 · dashboard/pages/await_tree.tsx:88 — all 3 copies are in the same file, and the CITED SPAN is not a self-contained block — it runs from inside one construct into the next (the tail of a branch plus the head of the following one, a run of switch arms, the end of a declaration plus the list that follows it) rather than covering a whole unit. So do not lift these lines literally: no call can be substituted for a half-open construct. Extract the enclosing repeated UNIT instead — the whole function, component or branch these lines sit in — and where the repetition IS the construct (a run of switch arms, a stack of near-identical declarations) replace it with one table or registry looked up by key rather than a helper each arm calls. The copies still drift apart the first time only one of them is edited, which is why this is reported.
Duplicated block (8 lines × 2 locations) dashboard/pages/fragment_graph.tsx:454— dashboard/pages/fragment_graph.tsx:454 · dashboard/pages/fragment_graph.tsx:462 — both copies are in the same file, so extract the block into one function there and call it from each site — the copies drift apart the first time only one of them is edited.
Unused dependency '16' — Declared in dashboard/package.json but never imported anywhere in that package or its workspace members — no static import reaches it. Usually that is dead weight and attack surface, but two shapes are indistinguishable from source and are NOT dead: an optional or native peer that another dependency loads dynamically at runtime, and a package a build, docs or test step installs and invokes separately. Confirm which of the three this is before removing it.
Unused dependency '@testing-library/react' — Declared in dashboard/package.json but never imported anywhere in that package or its workspace members — no static import reaches it. Usually that is dead weight and attack surface, but two shapes are indistinguishable from source and are NOT dead: an optional or native peer that another dependency loads dynamically at runtime, and a package a build, docs or test step installs and invokes separately. Confirm which of the three this is before removing it.
Unused dependency 'd3-axis' — Declared in dashboard/package.json but never imported anywhere in that package or its workspace members — no static import reaches it. Usually that is dead weight and attack surface, but two shapes are indistinguishable from source and are NOT dead: an optional or native peer that another dependency loads dynamically at runtime, and a package a build, docs or test step installs and invokes separately. Confirm which of the three this is before removing it.
SC1 · Supply-chain hygiene· NuGet dependencies are not locked · ×1
NuGet dependencies are not locked — No packages.lock.json and no central package management — restores aren't reproducible or pinned (SSDF PW.4.4). Enable <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile> (commit the lockfile) or adopt Directory.Packages.props. Advisory — never scored.
Off-boarding risk: anonymized user #1 — If anonymized user #1 becomes unavailable, 21 significant file(s) lose their only recent owner: src/stream/src/executor/backfill/snapshot_backfill/executor.rs, src/meta/src/barrier/edge_builder.rs, src/stream/src/executor/backfill/snapshot_backfill/consume_upstream/stream.rs, src/storage/src/hummock/vector/file.rs, src/storage/src/hummock/event_handler/uploader/spiller.rs, src/stream/src/executor/backfill/snapshot_backfill/vnode_stream.rs, src/stream/src/executor/backfill/snapshot_backfill/state.rs, src/meta/src/barrier/checkpoint/independent_job/mod.rs (+13 more). Pair on, review, or document these before any departure.
Off-boarding risk: anonymized user #2 — If anonymized user #2 becomes unavailable, 11 significant file(s) lose their only recent owner: src/frontend/src/optimizer/plan_visitor/datafusion_plan_converter.rs, src/frontend/src/datafusion/convert.rs, src/meta/src/manager/iceberg_pk_index_sink/mod.rs, src/stream/src/executor/iceberg_with_pk_index/position_delete_staging.rs, src/frontend/src/datafusion/iceberg_table_provider.rs, src/expr/impl/src/scalar/array_positions.rs, src/frontend/src/optimizer/plan_node/stream_iceberg_with_pk_index_position_delete_merger.rs, src/stream/src/from_proto/iceberg_with_pk_index/position_delete_merger.rs (+3 more). Pair on, review, or document these before any departure.
Off-boarding risk: anonymized user #3 — If anonymized user #3 becomes unavailable, 7 significant file(s) lose their only recent owner: src/meta/src/hummock/compaction/picker/non_overlap_sub_level_picker.rs, src/frontend/src/handler/alter_compaction_group.rs, src/storage/src/storage_failpoints/test_iterator.rs, src/storage/src/hummock/block_stream.rs, src/storage/hummock_sdk/src/filter_utils.rs, src/meta/src/hummock/manager/compaction/compact_task_builder.rs, src/storage/src/hummock/sstable/filter.rs. Pair on, review, or document these before any departure.
Off-boarding risk: anonymized user #4 — If anonymized user #4 becomes unavailable, 6 significant file(s) lose their only recent owner: src/frontend/src/optimizer/rule/mv_selection_rule.rs, src/stream/src/executor/source/iceberg_list_executor.rs, src/connector/src/sink/iceberg/metadata.rs, src/frontend/src/optimizer/plan_node/logical_gap_fill.rs, src/frontend/src/handler/vacuum.rs, src/frontend/src/catalog/system_catalog/rw_catalog/rw_iceberg_compaction_schedules.rs. Pair on, review, or document these before any departure.
Off-boarding risk: anonymized user #5 — If anonymized user #5 becomes unavailable, 6 significant file(s) lose their only recent owner: src/common/src/config/merge.rs, src/frontend/src/catalog/purify.rs, src/license/src/key.rs, src/frontend/src/optimizer/property/stream_kind.rs, src/license/src/rwu.rs, src/meta/src/rpc/await_tree.rs. Pair on, review, or document these before any departure.
Off-boarding risk: anonymized user #6 — If anonymized user #6 becomes unavailable, 4 significant file(s) lose their only recent owner: java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java, java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/openlineage/DebeziumOpenLineageEmitter.java, java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/connection/ServerInfo.java, src/storage/src/hummock/store/table_change_log_manager.rs. Pair on, review, or document these before any departure.
Off-boarding risk: anonymized user #7 — If anonymized user #7 becomes unavailable, 4 significant file(s) lose their only recent owner: java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresStreamingChangeEventSource.java, java/connector-node/risingwave-source-cdc/src/main/java/com/risingwave/connector/cdc/debezium/internal/OpendalSchemaHistory.java, src/jni_core/src/opendal_schema_history.rs, java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/mysql/MySqlStreamingChangeEventSource.java. Pair on, review, or document these before any departure.
Off-boarding risk: anonymized user #8 — If anonymized user #8 becomes unavailable, 3 significant file(s) lose their only recent owner: src/connector/src/source/pulsar/mod.rs, src/stream/src/executor/source/batch_source/mod.rs, e2e_test/source_inline/cdc/mysql/cron_only/extract_direct_cdc_current_offset.py. Pair on, review, or document these before any departure.
redundant comment integration_tests/client-library/csharp/NpgsqlTest.cs:15— "Create a new connection" — delete - the NpgsqlConnection constructor is self-describing
redundant comment integration_tests/client-library/csharp/NpgsqlTest.cs:18— "Open the connection" — delete - conn.Open() reads as this
redundant comment integration_tests/client-library/csharp/NpgsqlTest.cs:21— "Create a table if it doesn't exist" — delete - CREATE TABLE IF NOT EXISTS is obvious from the query, not the comment
redundant comment integration_tests/client-library/csharp/NpgsqlTest.cs:36— "Read the data" — delete - SELECT * FROM ... is self-evident
redundant comment integration_tests/client-library/csharp/NpgsqlTest.cs:136— "Assert.Equal(new string[] { "array", "value" }, reader["array_column"])" — delete - the comparison and column name are both plain text
D16 · Bus Factor· Further sole-owners (lower concentration) · ×1
Further sole-owners (lower concentration) — 6 other contributor(s) are each the sole owner of a small amount of code below the off-boarding threshold — folded into the bus-factor score and metrics (70 single-owned of 2006 analysed files in total, counted over production source files of roughly 2,400 bytes or more, excluding vendored, generated and example/demo trees and test files identified by path convention, largest first; 2006 of the 2876 production source files in this repository met that bar). They are anonymized user #9 (2 file(s)), anonymized user #10 (1 file(s)), anonymized user #11 (1 file(s)), anonymized user #12 (1 file(s)), anonymized user #13 (1 file(s)), anonymized user #14 (1 file(s)) — spread or document their files in the same way, at lower priority than the named off-boarding risks above.
Documentation: no architecture or design documentation ci/mongodb-tls/README.md— The README describes the MongoDB fixture but does not link to any documentation about the MongoDB sink configuration or TLS setup for RisingWave. Add a reference to the architecture docs that explain how MongoDB CDC with TLS is configured in RisingWave.
D28 · Secrets (history)· Rotate the exposed credentials · ×1
D34 · Knowledge Freshness· Further orphaned files (smaller) · ×1
Further orphaned files (smaller) — 416 smaller file(s) also have no living knowledge — folded into the freshness score and metrics rather than raised one row each — most significant first: src/expr/impl/src/aggregate/general.rs, dashboard/components/FragmentGraph.tsx, src/expr/impl/src/scalar/extract.rs, src/common/src/types/num256.rs, java/connector-node/risingwave-source-cdc/src/main/java/io/debezium/connector/postgresql/PostgresSchema.java, src/expr/impl/src/scalar/regexp.rs, src/storage/src/row_serde/value_serde.rs, src/frontend/src/binder/expr/function/aggregate.rs (and 408 more) (433 orphaned of 2006 analysed files in total, counted over production source files of roughly 2,400 bytes or more, excluding vendored, generated and example/demo trees and test files identified by path convention, largest first; 2006 of the 2876 production source files in this repository met that bar). Attach the read to the next change that touches one of them: have a second person review that change, and leave behind a short comment or test recording what the file is for, so the knowledge comes back at the cost of a change you were making anyway.
No ADRs — No Architecture Decision Records found — no conventional ADR directory, no numbered `NNNN-title` documents in any markup this check reads, and nothing ADR-shaped by content. Design rationale recorded elsewhere (a design-notes tree, a mailing list, pull-request discussion) is not visible to this check and is not re-findable per decision, so a future maintainer cannot ask why one choice was made and get an answer.
Logging is not universal — Only 55/80 runnable modules use logging (modules with no entry point or server are excluded — they are libraries a runnable module hosts). Silent: `.`, `.`, `dashboard`, `develop/sql_bench`, `e2e_test/iceberg` and 20 more.
R7 · Dead Code· Unused export 'formatUnixEpoch' · ×1
Unused export 'formatUnixEpoch' dashboard/lib/utils/timeUtils.ts:106— Nothing imports this binding — it is safe to review for removal.
No security response headers detected integration_tests/iceberg-sink/Dockerfile:1— No Content-Security-Policy / X-Frame-Options / X-Content-Type-Options configuration found — defense in depth, even when a reverse proxy could set them. This is reported because `REDACTED` builds the web-server image that serves this application, so the configuration that would carry these headers is in this repository and was read in full. (−2.0 on this card.)
Outdated: github.com/Shopify/sarama — `github.com/Shopify/sarama` is required at v1.37.2 in integration_tests/datagen/go.mod, but v1.61.1 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/Shopify/sarama@v1.61.1 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/apache/pulsar-client-go — `github.com/apache/pulsar-client-go` is required at v0.8.1 in integration_tests/datagen/go.mod, but v0.21.0 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/apache/pulsar-client-go@v0.21.0 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/brianvoe/gofakeit/v6 — `github.com/brianvoe/gofakeit/v6` is required at v6.16.0 in integration_tests/datagen/go.mod, but v6.28.0 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/brianvoe/gofakeit/v6@v6.28.0 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/go-sql-driver/mysql — `github.com/go-sql-driver/mysql` is required at v1.7.0 in integration_tests/datagen/go.mod, but v1.10.1 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/go-sql-driver/mysql@v1.10.1 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/jackc/pgx/v5 — `github.com/jackc/pgx/v5` is required at v5.9.2 in integration_tests/client-library/go/go.mod, but v5.11.0 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/jackc/pgx/v5@v5.11.0 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/lib/pq — `github.com/lib/pq` is required at v1.10.7 in integration_tests/datagen/go.mod, but v1.12.3 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/lib/pq@v1.12.3 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/linkedin/goavro/v2 — `github.com/linkedin/goavro/v2` is required at v2.9.8 in integration_tests/datagen/go.mod, but v2.15.0 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/linkedin/goavro/v2@v2.15.0 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/nats-io/nats.go — `github.com/nats-io/nats.go` is required at v1.33.1 in integration_tests/datagen/go.mod, but v1.54.0 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/nats-io/nats.go@v1.54.0 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/stretchr/testify — `github.com/stretchr/testify` is required at v1.11.1 in integration_tests/client-library/go/go.mod, but v1.12.1 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/stretchr/testify@v1.12.1 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: github.com/urfave/cli — `github.com/urfave/cli` is required at v1.22.10 in integration_tests/datagen/go.mod, but v1.22.17 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get github.com/urfave/cli@v1.22.17 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: go.uber.org/ratelimit — `go.uber.org/ratelimit` is required at v0.2.0 in integration_tests/datagen/go.mod, but v0.3.1 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get go.uber.org/ratelimit@v0.3.1 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: gonum.org/v1/gonum — `gonum.org/v1/gonum` is required at v0.12.0 in integration_tests/datagen/go.mod, but v0.17.0 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get gonum.org/v1/gonum@v0.17.0 && go mod tidy` and commit the updated go.mod and go.sum.
Outdated: google.golang.org/protobuf — `google.golang.org/protobuf` is required at v1.33.0 in integration_tests/datagen/go.mod, but v1.36.12 is the module's current release — so this build is missing every fix published since, including any security fix. Run `go get google.golang.org/protobuf@v1.36.12 && go mod tidy` and commit the updated go.mod and go.sum.
Appendix B — Reproduction & audit trail
Every external tool invocation behind a deep-scan dimension — the tool, its captured version, the exact command, how many findings it yielded, and a link to the retained raw output. To reproduce any finding: check out the same commit and run the command shown (repo-relative — never an absolute scratch path). The complete raw scanner output is retained verbatim under artifacts/raw/ (indexed in artifacts/raw/index.json); per-invocation exit codes and wall-clock durations are in sidecar.json — kept out of this table so the rendered report stays byte-identical across runs of the same commit.
semgrep: not applicable — No personal data was found crossing a boundary the PII/GDPR ruleset checks — nothing written to a log or console sink, placed in a URL or query string, or persisted to browser storage. That is a clean result for the LEAK surface only: this ruleset detects personal data escaping, it does not inventory the personal data a repository holds, so it is not evidence that this repository has no personal-data surface. The personal-data map (Appendix C) and the C1-C5 compliance cards are what speak to that.
runtime-hardening: not applicable — No Kubernetes/orchestration workloads found in the repository manifests; network egress policy is a cluster-native control that may live at the platform/firewall layer, so there is nothing to assess here.
runtime-hardening: not applicable — No Kubernetes/orchestration workloads found in the repository manifests; seccomp/AppArmor/SELinux confinement is a workload-level control, so there is nothing to assess here.
runtime-hardening: not applicable — No Kubernetes/orchestration workloads found in the repository manifests; runtime threat-detection and admission-control policy are cluster-level controls, so there is nothing to assess here.
Run 01a0eb87-a818-7811-8f37-fb0d91e16150 · every finding is also locatable in findings.md, and the complete scoring record (with exit codes + durations) in sidecar.json.
Issues: 278 · Warnings: 2936 · Recommendations: 34 · Info: 13 — Appendix A · all findings · full markdown report.
Generated by Watchdog — deterministic code-health analysis. 29-09-2026 @ 04:58 UTC.
Downloadable artifacts
Machine-readable and reproducible from this commit + frozen rubric — drop them straight into a contract appendix, a CRA dossier, or a downstream SCA / VEX tool.