Skip to content

fix(column-bulk): backport column grid alphabetical sort to 1.13 (#29699)#29751

Open
sonika-shah wants to merge 3 commits into
1.13from
sonika/backport-column-grid-sort-1.13
Open

fix(column-bulk): backport column grid alphabetical sort to 1.13 (#29699)#29751
sonika-shah wants to merge 3 commits into
1.13from
sonika/backport-column-grid-sort-1.13

Conversation

@sonika-shah

@sonika-shah sonika-shah commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Backport of #29699 to 1.13

Backports #29699 (fix(column-bulk): sort column grid results alphabetically by column name) into the 1.13 release line. Refs #29698.

Problem

Column Bulk Operations rendered the column list in an arbitrary order — the aggregators request ascending order from the search engine, but the results are collected into a HashMap and ColumnMetadataGrouper.groupColumns emits rows in map (hash-bucket) iteration order without re-sorting. So the grid appeared unsorted.

Fix

Sort the output gridItems by columnName (ascending, case-insensitive) before returning from ColumnMetadataGrouper.groupColumns, with a case-sensitive tie-breaker so names differing only in case stay stable. Both engines and all query paths (browse / pattern / tag) route through this method, so the single change makes ordering deterministic everywhere.

Cherry-picked from main (bd1cef723b); applied cleanly to 1.13.

Verification

  • mvn clean install -DskipTests (backend) — BUILD SUCCESS.
  • ColumnMetadataGrouperTest — 10/10 pass (7 existing + 3 new: ascending order, case-insensitive, case-only-collision determinism).
  • Validated on a 2.0.0-SNAPSHOT build across browse, search, filter combinations, and pagination — all return deterministically alphabetical.

Greptile Summary

This PR makes column bulk grid results deterministic. The main changes are:

  • Sorts grouped column grid rows by column name.
  • Uses case-insensitive ordering with a case-sensitive tie breaker.
  • Skips malformed null column-name buckets.
  • Adds unit tests for ordering and null-name handling.

Confidence Score: 4/5

This is close, but the case-only paging behavior should be fixed before merging.

  • The null-name crash path is handled at the grouper boundary.
  • The final sorter preserves case-only variants, but some upstream paged inputs still collapse those variants before grouping.
  • Catalogs with Name and name can return an incomplete column list on pattern or tag queries.

Column grid sorting and upstream name pagination.

Important Files Changed

Filename Overview
openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java Adds null-key handling and deterministic column-name sorting, but the new case-only ordering contract is not matched by all upstream paged inputs.
openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnMetadataGrouperTest.java Adds focused tests for sorted output, case-only ordering, and null-name handling.

Reviews (3): Last reviewed commit: "fix(column-bulk): skip null-named column..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used:

  • Context used - CLAUDE.md (source)
  • Context used - openmetadata-ui-core-components/CLAUDE.md (source)

…ame (#29699)

* fix(column-bulk): sort column grid results alphabetically by column name

The column grid rendered rows in HashMap iteration order because
ColumnMetadataGrouper.groupColumns emitted them in entrySet order without
sorting, discarding the ascending order the aggregators request from the
search engine. Sort gridItems by columnName (case-insensitive) so the grid
is deterministic and alphabetical across both engines and all query paths.

Fixes #29698

* test/fix: deterministic tie-breaker + robust ordering tests

Address review feedback on the column grid sort:
- Add a case-sensitive tie-breaker (.thenComparing) so column names differing
  only in case have a stable order instead of falling back to map iteration.
- Use LinkedHashMap with deliberately non-sorted insertion in the sort tests so
  the unsorted input is deterministic (not reliant on HashMap iteration order).
- Add a test asserting case-only collisions sort deterministically.

* docs: clarify sort comment does not assert caller map type

* docs: tighten sort comment and make test comments generic

* docs: reword sort comment to say iteration order is not guaranteed
@github-actions

github-actions Bot commented Jul 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. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

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 Jul 5, 2026
@github-actions

github-actions Bot commented Jul 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.

Guard the column-name comparator with Comparator.nullsLast so a null
column name (e.g. a null map key) sorts last instead of throwing an NPE.
Adds a test covering the null case.
@github-actions

github-actions Bot commented Jul 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.

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

🟡 Playwright Results — all passed (19 flaky)

✅ 3664 passed · ❌ 0 failed · 🟡 19 flaky · ⏭️ 26 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 2 733 0 2 7
🟡 Shard 3 778 0 3 2
🟡 Shard 4 756 0 1 9
🟡 Shard 5 687 0 6 0
🟡 Shard 6 710 0 7 8
🟡 19 flaky test(s) (passed on retry)
  • Features/BulkEditEntity.spec.ts › Database Schema (shard 2, 1 retry)
  • Features/CustomMetric.spec.ts › Column custom metric (shard 2, 1 retry)
  • Features/Permissions/GlossaryPermissions.spec.ts › Team-based permissions work correctly (shard 3, 1 retry)
  • Features/Table.spec.ts › Tags term should be consistent for search (shard 3, 1 retry)
  • Flow/IngestionBot.spec.ts › Ingestion bot should be able to access domain specific domain (shard 3, 1 retry)
  • Pages/Domains.spec.ts › Rename domain with owners and experts preserves assignments (shard 4, 1 retry)
  • Pages/ExplorePageRightPanel.spec.ts › Should display and verify schema fields for dashboardDataModel (shard 5, 1 retry)
  • Pages/ExplorePageRightPanel.spec.ts › Should navigate to lineage and test controls for dashboardDataModel (shard 5, 1 retry)
  • Pages/ExplorePageRightPanel.spec.ts › Should allow Data Steward to edit description for dashboardDataModel (shard 5, 1 retry)
  • Pages/ExplorePageRightPanel.spec.ts › Should allow Data Steward to edit tier for dashboardDataModel (shard 5, 1 retry)
  • Pages/ExplorePageRightPanel.spec.ts › Should allow Data Steward to view all tabs for dashboardDataModel (shard 5, 1 retry)
  • Pages/ExplorePageRightPanel.spec.ts › Should NOT show restricted edit buttons for Data Steward for searchIndex (shard 5, 1 retry)
  • Pages/Glossary.spec.ts › Column dropdown drag-and-drop functionality for Glossary Terms table (shard 6, 1 retry)
  • Pages/InputOutputPorts.spec.ts › Remove last port shows empty state (shard 6, 1 retry)
  • Pages/InputOutputPorts.spec.ts › Lineage controls work (shard 6, 1 retry)
  • Pages/InputOutputPorts.spec.ts › Lineage section collapse/expand (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/TestSuite.spec.ts › Logical TestSuite (shard 6, 1 retry)
  • 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

…required field

A null column name (columnName is required in the column-grid response) is now
skipped when building rows, so a malformed bucket is dropped and the remaining
valid columns are returned. This also avoids the sort NPE at the source; the
comparator keeps nullsLast as a backstop. Test updated to assert the null-named
row is dropped.
@github-actions

github-actions Bot commented Jul 6, 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.

@gitar-bot

gitar-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 1 resolved / 1 findings

Backports deterministic alphabetical sorting to the column bulk grid by implementing case-insensitive ordering with a null-safe comparator. No issues found.

✅ 1 resolved
Edge Case: Sort comparator will NPE if a column name key is null

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnMetadataGrouper.java:109-111
In groupColumns, the new sort uses Comparator.comparing(ColumnGridItem::getColumnName, String.CASE_INSENSITIVE_ORDER).thenComparing(ColumnGridItem::getColumnName). columnName is set from entry.getKey() (the map key). If any caller ever inserts a null key (a HashMap permits one null key), String.CASE_INSENSITIVE_ORDER throws a NullPointerException, whereas before the sort the method returned results without dereferencing the name. Column names from the search index are realistically non-null, so this is low-probability, but the sort introduces a new failure mode that did not previously exist. If null keys are conceivable, guard with Comparator.nullsLast(...) (or nullsFirst) around the key comparators to keep ordering deterministic and crash-free.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

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.

1 participant