Skip to content

Fixes #27825: table type custom property conditions always evaluate to false in workflows - #33174

Closed
anuj-kumary wants to merge 10 commits into
mainfrom
fix-table-type-querybuilder-rules
Closed

Fixes #27825: table type custom property conditions always evaluate to false in workflows#33174
anuj-kumary wants to merge 10 commits into
mainfrom
fix-table-type-querybuilder-rules

Conversation

@anuj-kumary

Copy link
Copy Markdown
Member

Describe your changes:

Fixes #27825

A table-type custom property stores its value as an array of row objects under extension.<property>.rows, but the query builder registered each table column as a flat text field keyed <property>.rows.<column>. In JsonLogic output mode (workflow check conditions, data contract semantics) this serialized rules like:

{"and": [{"==": [{"var": "extension.Tabel.rows.Name"}, "anuj"]}]}

Since rows is an array, that var path never resolves at evaluation time, so the workflow condition always evaluated false.

In SearchOutputType.JSONLogic mode the table property is now registered as a !group field with mode: 'some' (keyed <property>.rows, one text subfield per column) — the same pattern already used for Owners/Tags/Domain — so react-awesome-query-builder emits and re-imports the correct per-row rule:

{"and": [{"some": [{"var": "extension.tableType.rows"}, {"==": [{"var": "name"}, "karan"]}]}]}

SearchOutputType.ElasticSearch mode (Explore advanced search) keeps the existing flat dotted fields, since the search index flattens the rows — no behavior change there.

Files changed:

  • src/utils/AdvancedSearchClassBase.tstable-cp case in buildMultiValueCustomPropertySubFields now branches on searchOutputType; OMField/builder signatures widened from Field to FieldOrGroup.
  • src/utils/AdvancedSearchUtils.tsxprocessCustomPropertyField guards the valueSources access, since group fields don't carry one.

Note: workflows that saved a rule with the old broken flat path will show an unrecognized field when the condition is edited (the stored rows.<column> field key no longer exists) — those rules never worked and need to be re-selected once. Newly created/edited rules generate the correct shape.

Type of change:

  • Bug fix

High-level design:

N/A — small change.

Tests:

Use cases covered

  • Creating a workflow check condition on a table-type custom property column generates a per-row some JsonLogic rule that evaluates true when any row matches (previously always false).
  • Editing a saved workflow re-imports the some rule back into the query builder tree (round-trip through QbUtils.loadFromJsonLogicjsonLogicFormat).
  • Explore advanced search (ElasticSearch output) on table-type custom properties keeps the existing flat column fields.

Unit tests

  • I added unit tests for the new/changed logic.
  • Files added/updated:
    • src/utils/AdvancedSearchClassBase.test.ts — new: table-cp + JSONLogic output returns a some-mode !group with per-column subfields; table-cp + ElasticSearch output keeps flat column fields.
    • src/utils/JSONLogicSearchClassBase.test.ts — new round-trip test: builds the real table-property config, imports the expected some rule via QbUtils.loadFromJsonLogic, and asserts QbUtils.jsonLogicFormat re-emits it identically with zero errors.
  • All affected suites pass: AdvancedSearchClassBase.test.ts, JSONLogicSearchClassBase.test.ts, AdvancedSearchUtils.test.tsx, QueryBuilderWidgetV1.test.tsx, AdvanceSearchProvider.test.tsx — 187 tests, 0 failures. tsc --noEmit introduces no new errors vs the main baseline; ESLint/Prettier/organize-imports clean on changed files.

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not added — the fix is in pure rule-generation utils covered by the unit + round-trip tests above; no visual/DOM change to assert.

Manual testing performed

Verification was done through the automated round-trip test that reproduces the exact rule from the issue. To verify manually:

  1. Settings → Custom Properties → Table: add a table-type custom property (e.g. tableType with columns name, age).
  2. On a table entity, set the property with a row name = karan.
  3. Governance → Workflows: create a workflow with a Check Condition node filtering on Custom Properties > tableType > name = karan.
  4. Inspect the saved node config: rules is now {"and":[{"some":[{"var":"extension.tableType.rows"},{"==":[{"var":"name"},"karan"]}]}]} and the workflow takes the true branch for the matching table.

UI screen recording / screenshots:

Not applicable — no visual change; the fix alters the JsonLogic rule serialization inside the query builder utils.

Checklist:

  • I have read the CONTRIBUTING document.

  • My PR title is Fixes <issue-number>: <short explanation>

  • My PR is linked to a GitHub issue via Fixes #<issue-number> above.

  • I have commented on my code, particularly in hard-to-understand areas.

  • For JSON Schema changes: not needed — no schema changes.

  • For UI changes: no visual change, recording not applicable.

  • I have added tests (unit / integration / Playwright as applicable) and listed them above.

  • I have added a test that covers the exact scenario we are fixing (round-trip test in JSONLogicSearchClassBase.test.ts reproduces the rule shape from table type custom property conditions always evaluate to false while creating a workflow #27825).

🤖 Generated with Claude Code

…m properties

Table custom properties store their values as an array of row objects under
extension.<property>.rows, but the query builder registered each column as a
flat text field (extension.<property>.rows.<column>). In JsonLogic output mode
(workflows, data contract semantics) that produced rules like
{"==":[{"var":"extension.prop.rows.Col"},"x"]} whose var path never resolves,
so the condition always evaluated false.

In JSONLogic output mode the table property is now registered as a !group
field with mode "some" (one subfield per column), so react-awesome-query-builder
emits and re-imports
{"some":[{"var":"extension.prop.rows"},{"==":[{"var":"Col"},"x"]}]},
matching how JsonLogic evaluates arrays of objects. ElasticSearch output mode
keeps the flat dotted fields since the search index flattens the rows.

Fixes #27825

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the UI UI specific issues label Sep 11, 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!

@anuj-kumary anuj-kumary self-assigned this Sep 11, 2026
@anuj-kumary anuj-kumary added safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check labels Sep 11, 2026
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 70%
70.92% (96321/135814) 55.6% (57222/102909) 56.94% (19065/33481)

…and use sidebarClick

The tests timed out in CI because the OSS environment does not expose
the Governance > Workflows navigation. Guard the entire describe with
`if (!process.env.PLAYWRIGHT_IS_OSS)` — matching the existing
WorkflowOssRestrictions pattern — so the tests only run in enterprise
CI shards where the governance API and sidebar are available.

Also:
- Replace manual sidebar hover+click with `sidebarClick()` utility
- Add `test.slow()` per test since workflow UI interactions are heavyweight
- Remove `test.skip()` calls (banned by playwright/no-skipped-test rule)

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

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

…rties

Revert all unnecessary type changes and limit the fix to the table-cp
case only. In JSONLogic output mode, delegate to a new private method
buildTableCustomPropertyGroup that emits select-typed column fields.
ElasticSearch mode keeps the existing flat text fields unchanged.

No changes to AdvancedSearchUtils.tsx, OMField type, or FieldOrGroup
imports — only AdvancedSearchClassBase.ts is modified.

Fixes #27825

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

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

…rties

Table custom properties store rows as an array. RAQB emits a flat var
path (extension.<cp>.rows.<column>) that never resolves against the
array at runtime, so conditions always evaluated false.

Post-process the JsonLogic output: rewriteTableCpRulesToSome converts
flat table-CP rules to the per-row some pattern and
rewriteTableCpSomeToFlat reverses it on import so RAQB can load the
tree. No field registration changes — the UI picker stays as-is.

Fixes #27825

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

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

Comment thread openmetadata-ui/src/main/resources/ui/src/utils/JSONLogicSearchClassBase.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

2 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

mapLogicChildren only descended into and/or but skipped {"!": ...}
wrappers. Operators like not_like emit {"!": {"like": [var, val]}}
and the inner comparison was never rewritten, keeping the broken flat
path. Now recurses into the ! operand as well.

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

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

Comment on lines +1607 to +1621
return [
{
subfieldsKey: field.name,
dataObject: {
type: '!group',
mode: 'some',
label,
subfields: Object.fromEntries(
columns.map((columnName) => [
columnName,
{
type: 'select',
label: columnName,
operators: LIST_VALUE_OPERATORS,
valueSources: ['value'],

@gitar-bot gitar-bot Bot Sep 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: Table-CP group key omits '.rows', var path may not resolve

buildTableCustomPropertyGroup registers the !group with subfieldsKey: field.name (e.g. tableType), so RAQB's some var resolves to extension.tableType rather than the array at extension.tableType.rows. The removed rewrite code (rewriteTableCpRulesToSome) explicitly used ${arrayPath}.rows as the some array var, and the PR's own target shape is {"some":[{"var":"extension.tableType.rows"},...]}. If the group key does not end in .rows, some iterates the row-container object instead of the rows array and the workflow condition still evaluates false — the exact bug #27825. Verify the emitted var path (there is no round-trip test asserting it); if it lacks .rows, set subfieldsKey: \${field.name}.rows``.

Key the group by the rows array path so the some var resolves to the array.:

return [
  {
    subfieldsKey: `${field.name}.rows`,
    dataObject: {
      type: '!group',
      mode: 'some',
      label,
      subfields: Object.fromEntries(

Was this helpful? React with 👍 / 👎

Comment on lines +1617 to +1622
{
type: 'select',
label: columnName,
operators: LIST_VALUE_OPERATORS,
valueSources: ['value'],
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Quality: table-cp select subfields lack option values for 'some' group

The group subfields are registered as type: 'select' with valueSources: ['value'] but no fieldSettings.listValues/asyncFetch, whereas the ElasticSearch flat branch uses type: 'text'. A select widget with no options may render an empty dropdown, preventing the user from entering a value for the per-row condition. Confirm a free-text/value entry is possible; otherwise use type: 'text' (matching the flat branch) or supply list values.

Was this helpful? React with 👍 / 👎

Comment on lines +1555 to +1557
if (searchOutputType === SearchOutputType.JSONLogic) {
return this.buildTableCustomPropertyGroup(field, label, columns);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Quality: Claimed JSONLogic table-CP unit/round-trip tests appear absent

The PR description states a table-cp + JSONLogic test returning a some-mode !group and a round-trip test in JSONLogicSearchClassBase.test.ts were added, but the table-cp tests in AdvancedSearchClassBase.test.ts only cover the ElasticSearch flat path and no extension.*.rows/loadFromJsonLogic assertion is present. The new JSONLogic branch and buildTableCustomPropertyGroup are therefore unverified by tests, which is why the missing-.rows risk above is undetected. Add a test asserting the emitted some var path.

Was this helpful? React with 👍 / 👎

@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

anuj-kumary and others added 2 commits September 11, 2026 16:28
…rties

In JSONLogic output mode, register table-type custom property columns
as a !group with mode "some" so RAQB emits per-row rules instead of
the flat dotted path that never resolves against the rows array.

Fixes #27825

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

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 759 → 759
- 0 added, 0 removed, 2 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/sidebar.ts
  openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

@gitar-bot

gitar-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Code Review ⚠️ Changes requested 3 resolved / 6 findings

Fixes table-type custom property conditions in workflows to emit per-row some JsonLogic rules instead of flat paths that never resolve. However, three issues must be addressed: the group key omits .rows so the some var may not resolve to the rows array (the exact bug #27825), the subfields lack option values for the select widget, and the claimed JSONLogic unit and round-trip tests are absent — verify the emitted var path matches extension.tableType.rows, confirm free-text value entry works, and add tests asserting the correct some rule shape before merge.

⚠️ Bug: Table-CP group key omits '.rows', var path may not resolve

📄 openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1607-1621

buildTableCustomPropertyGroup registers the !group with subfieldsKey: field.name (e.g. tableType), so RAQB's some var resolves to extension.tableType rather than the array at extension.tableType.rows. The removed rewrite code (rewriteTableCpRulesToSome) explicitly used ${arrayPath}.rows as the some array var, and the PR's own target shape is {"some":[{"var":"extension.tableType.rows"},...]}. If the group key does not end in .rows, some iterates the row-container object instead of the rows array and the workflow condition still evaluates false — the exact bug #27825. Verify the emitted var path (there is no round-trip test asserting it); if it lacks .rows, set subfieldsKey: \${field.name}.rows``.

Key the group by the rows array path so the `some` var resolves to the array.
return [
  {
    subfieldsKey: `${field.name}.rows`,
    dataObject: {
      type: '!group',
      mode: 'some',
      label,
      subfields: Object.fromEntries(
💡 Quality: table-cp select subfields lack option values for 'some' group

📄 openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1617-1622

The group subfields are registered as type: 'select' with valueSources: ['value'] but no fieldSettings.listValues/asyncFetch, whereas the ElasticSearch flat branch uses type: 'text'. A select widget with no options may render an empty dropdown, preventing the user from entering a value for the per-row condition. Confirm a free-text/value entry is possible; otherwise use type: 'text' (matching the flat branch) or supply list values.

💡 Quality: Claimed JSONLogic table-CP unit/round-trip tests appear absent

📄 openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1555-1557 📄 openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1602-1616

The PR description states a table-cp + JSONLogic test returning a some-mode !group and a round-trip test in JSONLogicSearchClassBase.test.ts were added, but the table-cp tests in AdvancedSearchClassBase.test.ts only cover the ElasticSearch flat path and no extension.*.rows/loadFromJsonLogic assertion is present. The new JSONLogic branch and buildTableCustomPropertyGroup are therefore unverified by tests, which is why the missing-.rows risk above is undetected. Add a test asserting the emitted some var path.

✅ 3 resolved
Edge Case: Second test mutates shared workflow, unsafe on retry

📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Workflows/TableCpCheckCondition.spec.ts:296-310
The workflow is created once in beforeAll and both tests operate on it. The second test adds a 'Role' rule and saves it via PUT, then asserts exactly 2 conditions (expect(conditions.length).toBe(2)). If this test is retried by Playwright (or the suite is re-run without recreating the workflow), the previously persisted Role rule remains, so the retry produces 3 conditions and the assertion fails. Consider recreating/resetting the workflow per test (beforeEach) or asserting on the presence of the Role some condition rather than an exact count.

Bug: JSONLogic table-CP reverted to flat path — bug #27825 returns

📄 openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1555-1556 📄 openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1602-1616
For SearchOutputType.JSONLogic, buildTableCustomPropertyGroup now emits flat dotted subfield keys ${field.name}.rows.${columnName}, so QbUtils.jsonLogicFormat serializes {"==": [{"var": "extension.<name>.rows.<column>"}, value]}. Since extension.<name>.rows is an array of row objects, that var path never resolves at evaluation time and the workflow condition always evaluates false — the exact bug this PR (#27825) set out to fix, as the now-deleted code comment explained. No compensating transform to a some shape exists in JSONLogicSearchClassBase (its some handling only rewrites existing !group/mode:'some' fields like owners/domain). Restore the per-row !group with mode: 'some' (keyed ${field.name}.rows, one subfield per column) for JSONLogic mode, which requires re-widening OMField/builder return types back to FieldOrGroup.

Edge Case: Table-CP rewrite skips negated ops and NOT-wrapped rules

📄 openmetadata-ui/src/main/resources/ui/src/utils/JSONLogicSearchClassBase.ts:843-857 📄 openmetadata-ui/src/main/resources/ui/src/utils/JSONLogicSearchClassBase.ts:896-910
rewriteTableCpRulesToSome/rewriteTableCpSomeToFlat only descend through and/or (mapLogicChildren) and only transform a node when findComparisonOp finds a comparison operator with the {var} as its first argument. Rules that RAQB serializes as {"!": {...}} — e.g. a "not contains"/not_like or "Is Not Set" condition on a table-type custom-property column — are never traversed, so they keep the unresolvable flat extension.<cp>.rows.<column> path and still evaluate false (the exact #27825 bug), and they also fail to round-trip back to the query builder on edit. Equality operators (the primary case) are fixed and tested; consider recursing into ! (and other single-operand combinators) or documenting that only equality/plain-comparison operators are supported for table-CP columns in workflow conditions.

🤖 Prompt for agents
Code Review: Fixes table-type custom property conditions in workflows to emit per-row `some` JsonLogic rules instead of flat paths that never resolve. However, three issues must be addressed: the group key omits `.rows` so the `some` var may not resolve to the rows array (the exact bug #27825), the subfields lack option values for the select widget, and the claimed JSONLogic unit and round-trip tests are absent — verify the emitted var path matches `extension.tableType.rows`, confirm free-text value entry works, and add tests asserting the correct `some` rule shape before merge.

1. ⚠️ Bug: Table-CP group key omits '.rows', var path may not resolve
   Files: openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1607-1621

   buildTableCustomPropertyGroup registers the `!group` with `subfieldsKey: field.name` (e.g. `tableType`), so RAQB's `some` var resolves to `extension.tableType` rather than the array at `extension.tableType.rows`. The removed rewrite code (`rewriteTableCpRulesToSome`) explicitly used `${arrayPath}.rows` as the `some` array var, and the PR's own target shape is `{"some":[{"var":"extension.tableType.rows"},...]}`. If the group key does not end in `.rows`, `some` iterates the row-container object instead of the rows array and the workflow condition still evaluates false — the exact bug #27825. Verify the emitted var path (there is no round-trip test asserting it); if it lacks `.rows`, set `subfieldsKey: \`${field.name}.rows\``.

   Fix (Key the group by the rows array path so the `some` var resolves to the array.):
   return [
     {
       subfieldsKey: `${field.name}.rows`,
       dataObject: {
         type: '!group',
         mode: 'some',
         label,
         subfields: Object.fromEntries(

2. 💡 Quality: table-cp select subfields lack option values for 'some' group
   Files: openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1617-1622

   The group subfields are registered as `type: 'select'` with `valueSources: ['value']` but no `fieldSettings.listValues`/`asyncFetch`, whereas the ElasticSearch flat branch uses `type: 'text'`. A `select` widget with no options may render an empty dropdown, preventing the user from entering a value for the per-row condition. Confirm a free-text/value entry is possible; otherwise use `type: 'text'` (matching the flat branch) or supply list values.

3. 💡 Quality: Claimed JSONLogic table-CP unit/round-trip tests appear absent
   Files: openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1555-1557, openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchClassBase.ts:1602-1616

   The PR description states a `table-cp` + JSONLogic test returning a `some`-mode `!group` and a round-trip test in JSONLogicSearchClassBase.test.ts were added, but the table-cp tests in AdvancedSearchClassBase.test.ts only cover the ElasticSearch flat path and no `extension.*.rows`/loadFromJsonLogic assertion is present. The new JSONLogic branch and buildTableCustomPropertyGroup are therefore unverified by tests, which is why the missing-`.rows` risk above is undetected. Add a test asserting the emitted `some` var path.

Options

Display: compact → Counting what did not apply, without listing it.

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

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ UI Checkstyle passed — lint findings in changed files

🔍 ESLint findings in this PR's files — 0 error(s), 1 warning(s)

Errors block the build. Warnings do not yet — they are rules whose backlog is still
being worked down, listed so this PR does not add to it. See docs/ui-code-quality-gate.md.

0 error(s), 1 warning(s) across 1 changed file(s).

Count Rule
1 openmetadata-imports/no-circular-imports
All findings
Location Rule Message
🟡 src/utils/AdvancedSearchClassBase.ts:48:1 openmetadata-imports/no-circular-imports This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency.

Fix locally (fast - only checks files changed in this branch):

make ui-checkstyle-changed

@sonarqubecloud

Copy link
Copy Markdown

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

Labels

safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

table type custom property conditions always evaluate to false while creating a workflow

2 participants