Skip to content

Fixes #27162: table version history shows current datatype instead of historical one#27478

Open
miantalha45 wants to merge 9 commits intoopen-metadata:mainfrom
miantalha45:table-history-issue
Open

Fixes #27162: table version history shows current datatype instead of historical one#27478
miantalha45 wants to merge 9 commits intoopen-metadata:mainfrom
miantalha45:table-history-issue

Conversation

@miantalha45
Copy link
Copy Markdown

Problem

When viewing an older version of a table, the column type column always
showed the current datatype (e.g. decimal(15,3)) even if that version
had a different type (e.g. decimal(9,1)).

Root Cause

TableVersion was fetching columns via getTableColumnsByFQN, which
hits the current table columns API. This meant tableColumns always
held the latest data regardless of which version was being viewed. The
changeDescription for the selected version was then applied on top of
wrong base data, so the historical type was never shown correctly.

Fix

Removed the live API call and replaced it with local pagination over
currentVersionData.columns. The version API already returns the full
historical entity snapshot including columns, so no extra network call
is needed. Search filtering is also done locally.

Test

Added a unit test that verifies VersionTable receives columns with
the historical dataTypeDisplay value from currentVersionData, not
from any API response.

Proof

image image

Fixes #27162

Copilot AI review requested due to automatic review settings April 17, 2026 11:42
@miantalha45 miantalha45 requested a review from a team as a code owner April 17, 2026 11:42
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@miantalha45 miantalha45 changed the title Fix #27162: table version history shows current datatype instead of historical one Fixes #27162: table version history shows current datatype instead of historical one Apr 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes table version-history schema rendering so historical column dataTypeDisplay values come from the version snapshot (currentVersionData.columns) instead of the live “current table columns” API, addressing #27162.

Changes:

  • Removed live table-columns API usage from TableVersion and replaced it with local filtering + pagination over currentVersionData.columns.
  • Added a unit test asserting VersionTable receives historical dataTypeDisplay from currentVersionData.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
openmetadata-ui/src/main/resources/ui/src/components/Database/TableVersion/TableVersion.component.tsx Switches columns source to version snapshot and adds local search/pagination logic.
openmetadata-ui/src/main/resources/ui/src/components/Database/TableVersion/TableVersion.test.tsx Adds test ensuring historical column datatype display is passed through to VersionTable.
Comments suppressed due to low confidence (1)

openmetadata-ui/src/main/resources/ui/src/components/Database/TableVersion/TableVersion.component.tsx:137

  • paginationProps.isNumberBased is currently set to Boolean(searchText), but pagination is now always local/offset-based (no cursor-based API). When searchText is empty (default case), NextPrevious treats paging as cursor-based and disables both Next/Previous because paging.after/paging.before are undefined, effectively breaking column pagination. Set isNumberBased to true unconditionally for this view (or populate paging.after/before appropriately, but number-based is the natural fit for local slicing).
  const paginationProps = useMemo(
    () => ({
      currentPage,
      showPagination,
      isLoading: columnsLoading,
      isNumberBased: Boolean(searchText),
      pageSize,
      paging,
      pagingHandler: handleColumnsPageChange,
      onShowSizeChange: handlePageSizeChange,

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copilot AI review requested due to automatic review settings April 17, 2026 14:18
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment on lines +332 to +336
setTableColumns(filteredHistoricalColumns.slice(offset, offset + pageSize));
handlePagingChange({
offset,
limit: pageSize,
total: filteredHistoricalColumns.length,
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

The local paging state is updated with { offset, limit, total } only, leaving paging.after/paging.before unset. However NextPrevious disables Next/Previous in cursor mode when paging.after/before are missing. Since paginationProps.isNumberBased is still Boolean(searchText) (cursor mode when search is empty), this change can make column pagination non-functional by disabling both buttons. Align the paging mode with the data you provide: either always use number-based paging here, or compute/set after/before cursors for local pagination.

Suggested change
setTableColumns(filteredHistoricalColumns.slice(offset, offset + pageSize));
handlePagingChange({
offset,
limit: pageSize,
total: filteredHistoricalColumns.length,
const total = filteredHistoricalColumns.length;
const nextOffset = offset + pageSize;
const previousOffset = Math.max(offset - pageSize, 0);
setTableColumns(filteredHistoricalColumns.slice(offset, offset + pageSize));
handlePagingChange({
offset,
limit: pageSize,
total,
before: offset > 0 ? String(previousOffset) : undefined,
after: nextOffset < total ? String(nextOffset) : undefined,

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copilot AI review requested due to automatic review settings April 19, 2026 06:05
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment on lines +100 to +111
const filteredHistoricalColumns = useMemo(() => {
if (!searchText) {
return allHistoricalColumns;
}
const lower = searchText.toLowerCase();

setTableColumns(pruneEmptyChildren(response.data) || []);
handlePagingChange(response.paging);
} catch {
// Set empty state if API fails
setTableColumns([]);
handlePagingChange({
offset: 1,
limit: pageSize,
total: 0,
});
} finally {
setColumnsLoading(false);
}
},
[tableFqn, pageSize]
);
return allHistoricalColumns.filter(
(col) =>
col.name?.toLowerCase().includes(lower) ||
col.description?.toLowerCase().includes(lower)
);
}, [allHistoricalColumns, searchText]);
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

filteredHistoricalColumns only matches on top-level name and description, and it is not recursive. This changes search behavior vs VersionTable’s searchInColumns (which searches displayName, dataType, and children). Consider reusing the same searchInColumns logic (or an equivalent recursive filter) for the full historical column tree before slicing, so nested/typed matches aren’t dropped.

Copilot uses AI. Check for mistakes.
total: filteredHistoricalColumns.length,
});
setColumnsLoading(false);
}, [isVersionLoading, filteredHistoricalColumns, currentPage, pageSize]);
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

The useEffect dependency array omits handlePagingChange even though it’s used inside the effect. This is likely to trigger react-hooks/exhaustive-deps lint warnings and can capture a stale reference if the hook implementation changes. Add handlePagingChange to the dependency list (or refactor to avoid the effect).

Suggested change
}, [isVersionLoading, filteredHistoricalColumns, currentPage, pageSize]);
}, [
isVersionLoading,
filteredHistoricalColumns,
currentPage,
pageSize,
handlePagingChange,
]);

Copilot uses AI. Check for mistakes.
limit: pageSize,
total: filteredHistoricalColumns.length,
});
setColumnsLoading(false);
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

columnsLoading is now driven entirely by synchronous local filtering/slicing, but it still starts as true and is set to false in an effect. This will render the schema table in a loading state briefly even when isVersionLoading is false. Consider removing columnsLoading state entirely (or initialize it to false and only use it when truly async work is happening).

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copilot AI review requested due to automatic review settings April 20, 2026 05:02
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@gitar-bot
Copy link
Copy Markdown

gitar-bot bot commented Apr 20, 2026

Code Review ✅ Approved 1 resolved / 1 findings

Historical table versions now correctly display the associated datatype, resolving a discrepancy where only the current type was shown. The columnsLoading state correctly toggles back to true to ensure consistent data fetching.

✅ 1 resolved
Quality: columnsLoading state is never set back to true

📄 openmetadata-ui/src/main/resources/ui/src/components/Database/TableVersion/TableVersion.component.tsx:338
columnsLoading is initialized to true and set to false once the useEffect runs, but it's never set back to true on subsequent data changes (search/page changes). Since column slicing is now synchronous, columnsLoading is effectively unnecessary. Consider removing it or, if the loading skeleton is visually desirable on initial render, adding a comment explaining that it's only used for the initial mount.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment on lines +101 to +107
const filteredHistoricalColumns = useMemo(() => {
if (!searchText) {
return allHistoricalColumns;
}

// Use search API if there's a search query, otherwise use regular pagination
const response = searchQuery
? await searchTableColumnsByFQN(tableFqn, {
q: searchQuery,
limit: pageSize,
offset: offset,
fields: 'tags',
})
: await getTableColumnsByFQN(tableFqn, {
limit: pageSize,
offset: offset,
fields: 'tags',
});

setTableColumns(pruneEmptyChildren(response.data) || []);
handlePagingChange(response.paging);
} catch {
// Set empty state if API fails
setTableColumns([]);
handlePagingChange({
offset: 1,
limit: pageSize,
total: 0,
});
} finally {
setColumnsLoading(false);
}
},
[tableFqn, pageSize]
);
return searchInColumns(allHistoricalColumns, searchText);
}, [allHistoricalColumns, searchText]);
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

VersionTable already performs local column filtering based on its own searchText state, and this component now filters again via filteredHistoricalColumns. This duplicates work and can cause brief UI inconsistency (e.g., user types a search term and the child filters the current page slice before the parent updates pagination/slice). Consider making a single source of truth for filtering—either let TableVersion own search + pagination and disable the internal filtering in VersionTable for this usage, or pass the full (unfiltered) columns to VersionTable and let it handle filtering while TableVersion only handles pagination totals/offsets.

Copilot uses AI. Check for mistakes.
Comment on lines 322 to +333
useEffect(() => {
if (tableFqn && !isVersionLoading) {
// Reset to first page when search changes
fetchPaginatedColumns(currentPage, searchText || undefined);
if (isVersionLoading) {
return;
}
}, [
isVersionLoading,
tableFqn,
searchText,
fetchPaginatedColumns,
pageSize,
currentPage,
]);
const offset = (currentPage - 1) * pageSize;
setTableColumns(filteredHistoricalColumns.slice(offset, offset + pageSize));
handlePagingChange({
offset,
limit: pageSize,
total: filteredHistoricalColumns.length,
});
}, [isVersionLoading, filteredHistoricalColumns, currentPage, pageSize, handlePagingChange]);
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

tableColumns and the paging totals are only populated in a useEffect, so the first paint after isVersionLoading becomes false can render an empty VersionTable (and showPagination may be wrong) for one render cycle. To avoid a visible empty-state flash, initialize the paginated columns/paging synchronously (e.g., compute the slice in a useMemo and pass it directly, or initialize state from currentVersionData.columns, or switch this effect to useLayoutEffect).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UI] Table view history versions does not show historical datatypes is scale is changed

2 participants