Skip to content

fix(jdbi3): chunk IN-list batch queries to stay under DB parameter limit (#28752) - #28777

Merged
harshach merged 1 commit into
1.13from
harshach/cherry-pick-28752-to-1.13
Jun 5, 2026
Merged

fix(jdbi3): chunk IN-list batch queries to stay under DB parameter limit (#28752)#28777
harshach merged 1 commit into
1.13from
harshach/cherry-pick-28752-to-1.13

Conversation

@harshach

@harshach harshach commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Cherry-pick of #28752 onto the 1.13 branch.

What

Bulk subtree delete/restore fans an entire tree level's ids into a single IN (...) query. JDBI @BindList emits one bind parameter per element, so a level with ~100k entities (e.g. a service with 100k tables) exceeds PostgreSQL's 65,535 parameter ceiling and the operation fails. Adds EntityDAO.queryInChunks / updateInChunks helpers (chunk at MAX_IN_LIST_CHUNK_SIZE = 30_000, pass small lists straight through, dedup before chunking) and routes every @BindList batch method through them.

1.13 backport adaptation

  • Omitted the findToBatchAllTypes(List<Integer> relations, Include) chunking hunk and its findToBatchAllTypesWithRelationsCondition delegate — that overload originates in temporal lineage (Add temporal lineage traversal support #28426), which is not on 1.13. It has no callers on this branch.
  • Retargeted the two queryInChunks dedup / pass-through tests that exercised that overload to the existing int-relation findToBatchAllTypes overload (same queryInChunks code path), preserving coverage.

Verification

  • openmetadata-service compiles (main + test) under Java 21.
  • InListChunkingTest16/16 pass (0 failures, 0 errors).
  • mvn spotless:apply clean.

🤖 Generated with Claude Code

…mit (#28752)

* fix(jdbi3): chunk IN-list batch queries to stay under DB parameter limit

Bulk subtree delete/restore fans an entire tree level's ids into a single
IN (...) query. JDBI @BindList emits one bind parameter per element, so a
level with ~100k entities (e.g. a service with 100k tables) exceeds
PostgreSQL's 65,535 parameter ceiling ("Given query has 100,002 parameters")
and the operation fails. The reported findToBatchAllTypes crash was only the
first uncaught offender: getExtensionsBatch hits the same limit earlier but is
swallowed by populateRelationFields' per-entity fallback, and ~13 other
findToBatch*/findFromBatch* and tag batches were vulnerable in other paths.

Add EntityDAO.queryInChunks / updateInChunks helpers (chunk at
MAX_IN_LIST_CHUNK_SIZE, pass straight through for small lists so single-query
behavior is preserved) and route every @BindList batch method through them:
findToBatch*/findFromBatch*, entity_extension deleteAllBatch /
getExtensionsBatch / getExtensionBatch, and tag_usage getTagsInternalBatch /
getCertTagsInternalBatch. Also extract the duplicated deletedCondition(include)
clause builder.

Adds InListChunkingTest covering the chunk-size cap, exact input coverage
(no dropped/duplicated ids), and per-chunk result aggregation.

* fix(jdbi3): dedup ids before chunking IN-list batches

queryInChunks / updateInChunks split a large id list into chunks, so a
duplicate value landing in two different chunks would be queried (or deleted)
twice — duplicating result rows / issuing a redundant statement, unlike a
single IN (...) which ignores duplicate values. De-duplicate (encounter order
preserved) before chunking, matching the existing findEntitiesByIds pattern.

Adds InListChunkingTest cases covering duplicates split across a chunk
boundary for both the query and update helpers.

* fix(jdbi3): chunk three more unbounded IN-list paths

Audit of the remaining @BindList paths surfaced three more methods that fan a
caller-controlled, catalog-scaled list into one IN (...) and can hit the same
65,535 parameter ceiling. All routed through the queryInChunks/updateInChunks
helpers:

- EntityRelationshipDAO.bulkUpdateFromId — reparenting a glossary term updates
  every nested descendant's relationship row in one UPDATE; a subtree with
  >65k terms blew the cap. Now chunks toIds via updateInChunks.
- TagUsageDAO.deleteTagsByTargets — clearing column tags on a bulk table
  update/import passes every column FQN across the batch (wide/nested tables x
  ~100 per batch). Now chunks via updateInChunks.
- EntityTimeSeriesDAO.getLatestExtensionBatch — listing ingestion pipelines
  with fields=pipelineStatuses and a large limit (capped at 1,000,000) binds
  one FQN-hash per row. Now chunks via queryInChunks.

Adds InListChunkingTest cases for all three.

* test(jdbi3): cover IN-list chunking pass-through with duplicate ids

The existing tests all feed an over-limit list, leaving queryInChunks /
updateInChunks' else branch (size <= MAX_IN_LIST_CHUNK_SIZE) untested. Add two
cases proving a within-limit list with duplicates issues exactly one
query/statement and is passed through verbatim (no dedup) — the database
collapses the duplicates via IN(...) set semantics. Complements the existing
over-limit dedup tests, which assert against the distinct set.

* fix(jdbi3): chunk five more catalog-scaled IN-list paths

Follow-up to the IN-list chunking work — five more @BindList paths fan a catalog-scaled list into one IN (...) and can still hit the 65,535 parameter ceiling. All routed through the existing queryInChunks/updateInChunks helpers.

- EntityRelationshipDAO.bulkRemoveTo / bulkRemoveFrom: the 'remove' siblings of bulkUpdateFromId (already chunked). Reached via the bulkRemove{To,From}Relationship wrappers (their only callers) from DataProductRepository.batchMigrateAssetDomains (all assets of a type under one data product), TeamRepository, DomainRepository.
- UsageDAO.getLatestUsageBatch: GET /v1/tables?fields=usageSummary (and dashboards/pipelines/topics/mlmodels/...) resolves the field over the whole page via setFieldsInBulk; list limit is @max(1000000).
- DataQualityDataTimeSeriesDAO.getLatestRecordBatch: GET /v1/dataQuality/testCases?fields=testCaseResult, same whole-page resolution.
- TestCaseResultTimeSeriesDAO.listResultSummariesForTestSuites: GET /v1/dataQuality/testSuites?fields=summary, binds one id per executable test suite.

Adds InListChunkingTest cases for all five (16 tests pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Sriharsha Chintalapani <harsha@getcollate.io>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Sriharsha Chintalapani <harshach@users.noreply.github.com>

[1.13 backport] Dropped the findToBatchAllTypes(List<Integer> relations, Include)
chunking hunk and its findToBatchAllTypesWithRelationsCondition delegate: that
overload originates in temporal lineage (#28426), which is not on the 1.13 branch.
The two queryInChunks dedup / pass-through tests that exercised it were retargeted
to the existing int-relation findToBatchAllTypes overload (same queryInChunks path).
All 16 InListChunkingTest cases pass.

(cherry picked from commit 5af1ba5)
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Add a closing reference such as Fixes #12345 to the PR description (accepted keywords: Fixes, Closes, Resolves).

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

@github-actions github-actions Bot added backend safe to test Add this label to run secure Github workflows on PRs labels Jun 5, 2026
@gitar-bot

gitar-bot Bot commented Jun 5, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Implements queryInChunks and updateInChunks to safely batch JDBI3 IN clauses, preventing PostgreSQL parameter overflow for large entity sets. Verified via existing test coverage and clean compilation.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

The Python checkstyle failed.

Please run make py_format and py_format_check in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Python code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

@sonarqubecloud

sonarqubecloud Bot commented Jun 5, 2026

Copy link
Copy Markdown

@harshach
harshach merged commit f329dd4 into 1.13 Jun 5, 2026
27 of 53 checks passed
@harshach
harshach deleted the harshach/cherry-pick-28752-to-1.13 branch June 5, 2026 21:51
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

🟡 Playwright Results — all passed (18 flaky)

✅ 3890 passed · ❌ 0 failed · 🟡 18 flaky · ⏭️ 80 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 288 0 2 4
🟡 Shard 2 734 0 1 7
🟡 Shard 3 749 0 3 2
🟡 Shard 4 734 0 5 18
🟡 Shard 5 687 0 1 41
🟡 Shard 6 698 0 6 8
🟡 18 flaky test(s) (passed on retry)
  • Features/CustomizeDetailPage.spec.ts › Stored Procedure - customization should work (shard 1, 1 retry)
  • Pages/AuditLogs.spec.ts › should apply both User and EntityType filters simultaneously (shard 1, 2 retries)
  • Features/BulkEditEntity.spec.ts › Glossary (shard 2, 1 retry)
  • Features/Permissions/GlossaryPermissions.spec.ts › Team-based permissions work correctly (shard 3, 1 retry)
  • Flow/PersonaFlow.spec.ts › Set default persona for team should work properly (shard 3, 1 retry)
  • Pages/CustomProperties.spec.ts › Time Interval (shard 3, 1 retry)
  • Pages/CustomProperties.spec.ts › Table (shard 4, 1 retry)
  • Pages/DataContractsSemanticRules.spec.ts › Validate Description Rule Is_Not_Set (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Subdomain rename does not affect parent domain and updates nested children (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Multiple consecutive domain renames preserve all associations (shard 4, 1 retry)
  • Pages/Entity.spec.ts › Certification Add Remove (shard 4, 2 retries)
  • Pages/Entity.spec.ts › Delete Container (shard 5, 1 retry)
  • Features/AutoPilot.spec.ts › Agents created by AutoPilot should be deleted (shard 6, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for apiEndpoint -> dashboard (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify Impact Analysis service filter selection (shard 6, 1 retry)
  • Pages/Tag.spec.ts › Add and Remove Assets for Data Consumer (shard 6, 2 retries)
  • Pages/Tag.spec.ts › Add and Remove Assets for Data Steward (shard 6, 2 retries)
  • Pages/Users.spec.ts › Permissions for table details page for Data Consumer (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants