Skip to content

Conversation

@KCSAbeywickrama
Copy link
Contributor

@KCSAbeywickrama KCSAbeywickrama commented Nov 12, 2025

Purpose

Resolve wso2/product-ballerina-integrator#1664

Summary by CodeRabbit

Release Notes

  • New Features

    • Added JOIN clause support with dedicated editor and condition fields
    • Support for multiple source fields in array-based mappings
    • New ArrayJoin mapping type for complex array operations
    • Expanded query clause side panel for improved visibility
  • Improvements

    • Enhanced query node visualization with improved clause node handling
    • Better focus state management for mapped fields and root inputs
    • Refined port resolution and intermediate node processing logic

…eryExprLabelWidget references and clean up QueryOutputNode by removing unused query handling code
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

Walkthrough

This pull request adds JOIN clause support to the data mapper. Changes include a new JOIN enum member, updated data structures to track join expressions and root input focusing, new ClauseConnectorNode and related factories for UI rendering, support for ArrayJoin mapping type, and adjustments to node/port handling to accommodate multi-input field references and clause integration.

Changes

Cohort / File(s) Summary
Core Interface Updates
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts
Added JOIN to IntermediateClauseType enum; added lhsExpression, rhsExpression, and isOuter fields to IntermediateClauseProps; added focusInputRootMap to ExpandedDMModel and DMModel; added traversingRoot to DMModel; removed focusedMemberId from IOType
Data Processing & Root Tracking
workspaces/ballerina/ballerina-extension/src/rpc-managers/data-mapper/utils.ts, workspaces/ballerina/ballerina-visualizer/src/views/DataMapper/DataMapperView.tsx
Extended expandDMModel to include focusInputRootMap in output; initialize focusInputRootMap during input preprocessing and populate it when focus paths are detected; updated getModelSignature to incorporate query-level inputs
Context & Editor Setup
workspaces/ballerina/data-mapper/src/components/DataMapper/DataMapperEditor.tsx, workspaces/ballerina/data-mapper/src/utils/DataMapperContext/DataMapperContext.ts
Added hasInputsOutputsChanged parameter to DataMapperContext constructor; introduced hasInputsOutputsChanged property on IDataMapperContext interface
Clause UI Components
workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClauseEditor.tsx, workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx
Integrated with global store to manage clause editing state; added JOIN clause type support with lhsExpression and rhsExpression fields; expanded SidePanel width from 312 to 400; added useEffect to auto-focus last added clause
View Model Updates
workspaces/ballerina/data-mapper/src/components/DataMapper/Views/DataMapperView.ts
Changed sourceField from single string to sourceFields array to support multiple input field references
Intermediate & Connector Node Support
workspaces/ballerina/data-mapper/src/components/Diagram/Actions/IONodesScrollCanvasAction.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Actions/utils.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Diagram.tsx, workspaces/ballerina/data-mapper/src/components/Diagram/utils/focus-positioning-utils.ts
Added ClauseConnectorNode to intermediate node handling across action and positioning utilities; registered ClauseConnectorNodeFactory in diagram engine; extended node type filtering and update logic
New ClauseConnectorNode Implementation
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNodeFactory.tsx, workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNodeWidget.tsx, workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/index.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Node/index.ts
Introduced ClauseConnectorNode class with port initialization, link creation, and positioning logic; created factory for React component generation; added widget for UI rendering with diagnostics and action buttons
Link & Port Type Updates
workspaces/ballerina/data-mapper/src/components/Diagram/Link/DataMapperLink/DataMapperLink.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Port/model/InputOutputPortModel.ts
Added ArrayJoin mapping type to MappingType enum; added mapWithJoin handling for ArrayJoin pending mappings
Link Creation Logic
workspaces/ballerina/data-mapper/src/components/Diagram/LinkState/CreateLinkState.ts
Broadened target/source port resolution by removing isQueryHeaderPort checks; added ClauseConnectorNode handling for intermediate port target mapping
Label & Expression Updates
workspaces/ballerina/data-mapper/src/components/Diagram/Label/ExpressionLabelFactory.tsx, workspaces/ballerina/data-mapper/src/components/Diagram/Label/ExpressionLabelModel.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Label/QueryExprLabelWidget.tsx
Removed isQuery-based render path in ExpressionLabelFactory; added pendingMappingType guard with ArrayJoin check; removed isQuery property from ExpressionLabelModel and ExpressionLabelOptions; deleted QueryExprLabelWidget file
Node Port & Input Handling
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryExprConnector/QueryExprConnectorNodeWidget.tsx, workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryOutput/QueryOutputNode.ts, workspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/DataMapperNode.ts
Changed sourceField to sourceFields array handling in focusedFieldFQNs calculation; removed focusedMemberId-based member resolution; passed entire inputs array to expandArrayFn; removed automatic linking between input and query output in QueryOutputNode
Mapping & Array Expansion Logic
workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts
Updated getMappingType to return ArrayJoin when target port ends with ".\#" and dimension delta is zero; changed expandArrayFn signature from single inputId to inputIds array; updated baseView construction to use sourceFields
Node Utilities & Port Resolution
workspaces/ballerina/data-mapper/src/components/Diagram/utils/node-utils.ts, workspaces/ballerina/data-mapper/src/components/Diagram/utils/port-utils.ts
Broadened findInputNode return type to include SubMappingNode; replaced recursive fallback with focusInputRootMap lookup; updated getInputPort to accept InputNode or SubMappingNode
Modification & Join Handling
workspaces/ballerina/data-mapper/src/components/Diagram/utils/modification-utils.ts
Added new mapWithJoin function to construct and open join clause panel; wrapped input argument in array when calling expandArrayFn from mapWithQuery
Query & Clause State Management
workspaces/ballerina/data-mapper/src/store/store.ts
Added clauseToAdd state and setClauseToAdd setter to DataMapperQueryClausesPanelState; extended reset behavior to clear clauseToAdd
Model Traversal & Visitor Pattern
workspaces/ballerina/data-mapper/src/utils/model-utils.ts, workspaces/ballerina/data-mapper/src/visitors/BaseVisitor.ts, workspaces/ballerina/data-mapper/src/visitors/IntermediateNodeInitVisitor.ts
Added Query traversal after subMappings in traverseNode with new traverseQuery helper; extended BaseVisitor with beginVisitQuery and endVisitQuery lifecycle hooks; added beginVisitQuery in IntermediateNodeInitVisitor to create ClauseConnectorNodes
Diagram Caching
workspaces/ballerina/data-mapper/src/components/Diagram/hooks/useDiagramModel.ts
Added queryIOs derived from model.query.inputs and output to useDiagramModel React Query key for cache invalidation

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ClauseEditor
    participant Store as DMQueryClausesPanelStore
    participant ClauseConnectorNode
    participant LinkCreation

    User->>ClauseEditor: Opens clause editor
    ClauseEditor->>Store: Get clauseToAdd state
    ClauseEditor->>ClauseEditor: Derive current clause from store or props
    User->>ClauseEditor: Selects JOIN type
    ClauseEditor->>ClauseEditor: Show lhsExpression & rhsExpression fields
    User->>ClauseEditor: Fills join parameters
    User->>ClauseEditor: Submit form
    ClauseEditor->>Store: setClauseToAdd(undefined)
    ClauseEditor->>Store: Submit clause to panel
    Note over ClauseConnectorNode: Clause model created
    ClauseConnectorNode->>ClauseConnectorNode: initPorts() - gather source inputs
    ClauseConnectorNode->>ClauseConnectorNode: initLinks() - create mappings
    ClauseConnectorNode->>LinkCreation: Create source→inPort links
    LinkCreation->>LinkCreation: Wire selection listeners
    ClauseConnectorNode->>LinkCreation: Create outPort→target link
    Note over LinkCreation: Array inputs mapped to join operation
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • ClauseConnectorNode implementation (ClauseConnectorNode.ts, ClauseConnectorNodeFactory.tsx, ClauseConnectorNodeWidget.tsx) — Verify port initialization, link creation logic, and integration with query state; ensure selector event propagation works correctly
  • Mapping type logic in common-utils.ts — Review getMappingType decision tree for ArrayJoin vs ArrayToArray conditions; verify port name pattern matching (e.g., ".\#" suffix check)
  • Focus input root tracking — Confirm focusInputRootMap population during input preprocessing and correct lookup in node-utils.ts; verify integration with focusedFieldFQNs
  • Multi-input field references — Validate sourceField→sourceFields transition across all affected components and that expandArrayFn properly handles array of inputIds
  • Node linking changes — Review removal of focusedMemberId-based member resolution and focusInputRootMap lookup; confirm backward compatibility and correctness of SubMappingNode inclusion in node resolution
  • Link creation state management — Examine CreateLinkState changes removing isQueryHeaderPort guards; ensure all port types are handled correctly
  • Query visitor integration — Verify traverseQuery hook is invoked consistently and ClauseConnectorNode creation in IntermediateNodeInitVisitor aligns with visitor pattern expectations

Suggested labels

Checks/Enable UI Tests

Suggested reviewers

  • hevayo
  • gigara

Poem

🐰✨ A Clause to Celebrate

With JOIN now sprouted in the mapper's garden,
Clauses connect like carrots in a row,
Arrays dance as one, no more to harden,
Focus roots find home in each careful flow! 🌱

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is incomplete. It only includes the Purpose section with a link to the related issue, but lacks Goals, Approach, UI Component Development, and other required template sections. Complete the PR description by filling in the Goals, Approach, UI Component Development, Release note, and other applicable sections from the template to provide comprehensive documentation of the changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly summarizes the main change: adding support for the join clause in the BI Data Mapper, which aligns with the primary objective.
Linked Issues check ✅ Passed The code changes comprehensively implement frontend support for the join clause, including UI components, data structures, and logic to handle join operations as specified in issue #1664.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing join clause support. Some modifications extend existing infrastructure (e.g., UpdatedDataMapperLink model, modified expand array logic) but are necessary to support the new join functionality.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bi-dm-join-clause

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@KCSAbeywickrama KCSAbeywickrama marked this pull request as ready for review November 12, 2025 07:45
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx (1)

84-84: Clarify the width change rationale.

The panel width increased from 312 to 400 pixels. Consider documenting the reason for this change (e.g., accommodating wider clause content, improved UX).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90583e9 and 5949afc.

📒 Files selected for processing (36)
  • workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (4 hunks)
  • workspaces/ballerina/ballerina-extension/src/rpc-managers/data-mapper/utils.ts (3 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/DataMapper/DataMapperView.tsx (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/DataMapper/DataMapperEditor.tsx (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClauseEditor.tsx (6 hunks)
  • workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx (3 hunks)
  • workspaces/ballerina/data-mapper/src/components/DataMapper/Views/DataMapperView.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Actions/IONodesScrollCanvasAction.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Actions/utils.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Diagram.tsx (3 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Label/ExpressionLabelFactory.tsx (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Label/ExpressionLabelModel.ts (0 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Label/QueryExprLabelWidget.tsx (0 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Link/DataMapperLink/DataMapperLink.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/LinkState/CreateLinkState.ts (4 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNodeFactory.tsx (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNodeWidget.tsx (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/index.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryExprConnector/QueryExprConnectorNodeWidget.tsx (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryOutput/QueryOutputNode.ts (0 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/DataMapperNode.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/index.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Port/model/InputOutputPortModel.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/hooks/useDiagramModel.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts (3 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/utils/focus-positioning-utils.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/utils/modification-utils.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/utils/node-utils.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/components/Diagram/utils/port-utils.ts (1 hunks)
  • workspaces/ballerina/data-mapper/src/store/store.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/utils/DataMapperContext/DataMapperContext.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/utils/model-utils.ts (3 hunks)
  • workspaces/ballerina/data-mapper/src/visitors/BaseVisitor.ts (2 hunks)
  • workspaces/ballerina/data-mapper/src/visitors/IntermediateNodeInitVisitor.ts (2 hunks)
💤 Files with no reviewable changes (3)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Label/ExpressionLabelModel.ts
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryOutput/QueryOutputNode.ts
  • workspaces/ballerina/data-mapper/src/components/Diagram/Label/QueryExprLabelWidget.tsx
🧰 Additional context used
🧬 Code graph analysis (22)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/port-utils.ts (1)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts (1)
  • InputNode (29-160)
workspaces/ballerina/data-mapper/src/components/Diagram/Port/model/InputOutputPortModel.ts (1)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/modification-utils.ts (1)
  • mapWithJoin (179-202)
workspaces/ballerina/data-mapper/src/utils/model-utils.ts (2)
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (1)
  • ExpandedDMModel (118-129)
workspaces/ballerina/data-mapper/src/visitors/BaseVisitor.ts (1)
  • BaseVisitor (21-40)
workspaces/ballerina/data-mapper/src/components/Diagram/Diagram.tsx (1)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1)
  • ClauseConnectorNode (36-187)
workspaces/ballerina/data-mapper/src/visitors/BaseVisitor.ts (1)
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (1)
  • ExpandedDMModel (118-129)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNodeFactory.tsx (2)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (2)
  • ClauseConnectorNode (36-187)
  • CLAUSE_CONNECTOR_NODE_TYPE (33-33)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNodeWidget.tsx (1)
  • ClauseConnectorNodeWidget (35-84)
workspaces/ballerina/data-mapper/src/components/Diagram/LinkState/CreateLinkState.ts (2)
workspaces/ballerina/data-mapper/src/components/Diagram/Port/model/InputOutputPortModel.ts (1)
  • InputOutputPortModel (54-123)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1)
  • ClauseConnectorNode (36-187)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/node-utils.ts (2)
workspaces/ballerina/data-mapper/src/components/DataMapper/Views/DataMapperView.ts (1)
  • View (18-23)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts (1)
  • InputNode (29-160)
workspaces/ballerina/data-mapper/src/components/Diagram/Actions/utils.ts (1)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1)
  • ClauseConnectorNode (36-187)
workspaces/ballerina/ballerina-extension/src/rpc-managers/data-mapper/utils.ts (1)
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (1)
  • DMModel (131-144)
workspaces/ballerina/data-mapper/src/components/Diagram/Actions/IONodesScrollCanvasAction.ts (1)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1)
  • ClauseConnectorNode (36-187)
workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx (1)
workspaces/ballerina/data-mapper/src/store/store.ts (1)
  • useDMQueryClausesPanelStore (171-180)
workspaces/ballerina/data-mapper/src/store/store.ts (1)
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (1)
  • IntermediateClause (216-219)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (8)
workspaces/ballerina/data-mapper/src/components/Diagram/Port/model/InputOutputPortModel.ts (1)
  • InputOutputPortModel (54-123)
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (1)
  • DMDiagnostic (70-83)
workspaces/ballerina/data-mapper/src/utils/DataMapperContext/DataMapperContext.ts (1)
  • IDataMapperContext (21-35)
workspaces/ballerina/data-mapper/src/store/store.ts (1)
  • useDMSearchStore (83-89)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/node-utils.ts (1)
  • findInputNode (23-47)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/port-utils.ts (2)
  • getInputPort (26-37)
  • getTargetPortPrefix (60-73)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryOutput/QueryOutputNode.ts (1)
  • QueryOutputNode (37-186)
workspaces/ballerina/data-mapper/src/components/Diagram/Link/DataMapperLink/DataMapperLink.ts (1)
  • DataMapperLinkModel (37-95)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNodeWidget.tsx (5)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1)
  • ClauseConnectorNode (36-187)
workspaces/ballerina/data-mapper/src/components/styles.ts (1)
  • useIntermediateNodeStyles (297-336)
workspaces/ballerina/data-mapper/src/store/store.ts (2)
  • useDMExpressionBarStore (135-161)
  • useDMQueryClausesPanelStore (171-180)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/LinkConnector/LinkConnectorWidgetComponents.tsx (1)
  • renderPortWidget (26-32)
workspaces/common-libs/ui-toolkit/src/components/Codicon/Codicon.tsx (1)
  • Codicon (44-56)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts (1)
workspaces/ballerina/data-mapper/src/utils/DataMapperContext/DataMapperContext.ts (1)
  • IDataMapperContext (21-35)
workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClauseEditor.tsx (3)
workspaces/ballerina/data-mapper/src/store/store.ts (1)
  • useDMQueryClausesPanelStore (171-180)
workspaces/ballerina/ballerina-core/src/interfaces/bi.ts (1)
  • OptionProps (495-500)
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (4)
  • DMFormField (260-271)
  • DMFormFieldValues (273-275)
  • IntermediateClause (216-219)
  • IntermediateClauseProps (206-214)
workspaces/ballerina/data-mapper/src/components/DataMapper/DataMapperEditor.tsx (1)
workspaces/ballerina/data-mapper/src/components/DataMapper/Views/DataMapperView.ts (1)
  • View (18-23)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryExprConnector/QueryExprConnectorNodeWidget.tsx (1)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts (1)
  • expandArrayFn (226-266)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/focus-positioning-utils.ts (1)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1)
  • ClauseConnectorNode (36-187)
workspaces/ballerina/data-mapper/src/visitors/IntermediateNodeInitVisitor.ts (2)
workspaces/ballerina/ballerina-core/src/interfaces/data-mapper.ts (1)
  • Query (191-198)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/ClauseConnectorNode.ts (1)
  • ClauseConnectorNode (36-187)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/modification-utils.ts (3)
workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts (1)
  • expandArrayFn (226-266)
workspaces/ballerina/data-mapper/src/components/Diagram/Port/model/InputOutputPortModel.ts (1)
  • InputOutputPortModel (54-123)
workspaces/ballerina/data-mapper/src/store/store.ts (1)
  • useDMQueryClausesPanelStore (171-180)
🔇 Additional comments (33)
workspaces/ballerina/data-mapper/src/components/Diagram/hooks/useDiagramModel.ts (2)

50-50: Well-structured serialization for query IO tracking.

The queryIOs variable correctly derives a string representation from model.query.inputs and model.query.output, following a pattern similar to the existing mappings and subMappings serialization. This enables cache invalidation when query inputs or outputs change, which is essential for JOIN clause support.

Verify that model.query.output is a primitive or string type (not a complex object) to ensure .toString() produces stable, meaningful cache keys rather than [object Object].


103-104: Correctly extends queryKey for JOIN support.

Adding subMappings and queryIOs to the React Query queryKey array ensures the diagram model refetches when subMappings or query IOs change. This aligns perfectly with the PR objective of adding JOIN clause support, as changes to query inputs/outputs will now properly trigger diagram updates.

workspaces/ballerina/data-mapper/src/components/Diagram/Actions/utils.ts (2)

28-30: LGTM! ClauseConnectorNode properly classified.

The addition of ClauseConnectorNode to the imports and INTERMEDIATE_NODES set correctly integrates the new node type into the diagram action system.


46-50: LGTM! INTERMEDIATE_NODES array updated correctly.

The ClauseConnectorNode is properly added to the INTERMEDIATE_NODES array, enabling it to be recognized by isIntermediateNode() checks throughout the codebase.

workspaces/ballerina/data-mapper/src/components/Diagram/Link/DataMapperLink/DataMapperLink.ts (1)

27-35: LGTM! ArrayJoin mapping type added.

The new ArrayJoin enum member is properly added to support JOIN clause mappings. The naming follows the existing convention and integrates cleanly with the MappingType enum.

workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts (1)

57-60: LGTM! Correctly adapted to sourceFields array.

The change properly handles the new sourceFields array by using flatMap to flatten the array-of-arrays and filter(Boolean) to remove falsy values. This maintains correct behavior for multi-input JOIN scenarios.

workspaces/ballerina/data-mapper/src/utils/DataMapperContext/DataMapperContext.ts (2)

21-35: LGTM! Context interface extended with change tracking flag.

The addition of hasInputsOutputsChanged boolean property to the IDataMapperContext interface is clean and enables tracking input/output changes for JOIN support.


37-54: LGTM! Constructor parameter added with safe default.

The hasInputsOutputsChanged parameter is properly added to the constructor with a default value of false, preventing breaking changes for existing instantiations.

workspaces/ballerina/data-mapper/src/components/Diagram/Label/ExpressionLabelFactory.tsx (1)

37-45: All verification checks passed—code changes are intentional and correct.

The verification confirms:

  • QueryExprLabelWidget removal is complete: No references exist anywhere in the codebase
  • ArrayJoin empty rendering is intentional: ArrayJoin has special handling upstream (mapWithJoin is called explicitly in InputOutputPortModel.ts:79 when mapping type is ArrayJoin), indicating no widget/label should be displayed for this case
  • MappingType.ArrayJoin is properly defined and consistently handled across the codebase (common-utils.ts returns it based on port naming conventions)

The rendering logic correctly routes:

  1. ArrayJoin → empty fragment (no label/options shown, handled separately elsewhere)
  2. Other pending mappings → MappingOptionsWidget
  3. Default → ExpressionLabelWidget
workspaces/ballerina/data-mapper/src/components/Diagram/Node/QueryExprConnector/QueryExprConnectorNodeWidget.tsx (1)

76-76: No backward compatibility issues identified.

The change from mapping.inputs[0] to mapping.inputs is properly supported by expandArrayFn. The function accepts inputIds: string[] and directly assigns it to sourceFields without assuming array length, so both single-element arrays (existing behavior) and multi-element arrays (new JOIN behavior) work identically.

workspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/DataMapperNode.ts (1)

383-391: Verification inconclusive — request manual testing of array focusing behavior.

Based on codebase search:

  • focusedMemberId and resolveArrayMemberField are completely removed (no remaining references)
  • The simplification to direct attributes.field?.member access is correct in isolation
  • Array focus behavior is now handled via a different mechanism (focusedFieldFQNs)

However, without executing the actual test suite, I cannot confirm that focused array member selection still works correctly in all scenarios. The existing test at dataMapper.spec.ts:430 covers array mapping but may not specifically validate focused member behavior.

workspaces/ballerina/data-mapper/src/components/DataMapper/Views/DataMapperView.ts (1)

18-23: All View consumers properly updated for breaking interface change.

Verification confirms the breaking change from sourceField?: string to sourceFields?: string[] has been correctly implemented:

  • View creation at common-utils.ts:248-251 assigns sourceFields: inputIds where inputIds is explicitly typed as string[]
  • View consumption at InputNode.ts:58 correctly uses flatMap(view => view.sourceFields) for array handling
  • Initial View creation at DataMapperEditor.tsx:153 properly omits the optional sourceFields property
  • No references to the old singular sourceField property on View objects exist in the ballerina workspace
workspaces/ballerina/data-mapper/src/components/Diagram/Node/index.ts (1)

28-28: LGTM!

The export addition for ClauseConnector follows the existing pattern and properly extends the public API surface to include the new clause connector functionality.

workspaces/ballerina/data-mapper/src/utils/model-utils.ts (3)

19-19: LGTM!

The Query import is necessary for the new traverseQuery functionality.


46-49: LGTM!

The query traversal logic correctly uses optional chaining and follows the established pattern for visiting model elements.


85-88: LGTM!

The traverseQuery function follows the same pattern as other traverse functions (traverseInputType, traverseOutputType, traverseSubMappingType) and correctly delegates to the visitor's beginVisitQuery and endVisitQuery methods.

workspaces/ballerina/ballerina-visualizer/src/views/DataMapper/DataMapperView.tsx (1)

717-717: LGTM!

The signature calculation correctly extends the inputs array to include query-level inputs using optional chaining and appropriate fallback handling.

workspaces/ballerina/data-mapper/src/components/Diagram/utils/focus-positioning-utils.ts (2)

20-20: LGTM!

The import addition is necessary for the updated intermediate node handling logic.


160-160: LGTM!

The type union correctly includes ClauseConnectorNode alongside other intermediate connector types, following the established pattern for intermediate node resolution.

workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx (1)

71-78: Verify the effect cleanup behavior.

The cleanup function resets clauseToAdd to undefined on every render when dependencies change. This means if clauses.length changes while clauseToAdd is defined, it will reset the clause addition state, which might not be the intended behavior.

Consider whether the cleanup should only run on component unmount:

useEffect(() => {
    if (clauseToAdd) {
        setAdding(clauses.length - 1);
    }
    return () => {
        setClauseToAdd(undefined);
    }
}, [clauseToAdd]); // Remove clauses.length if it shouldn't reset on length change
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ClauseConnector/index.ts (1)

18-20: LGTM!

The barrel export file follows the standard pattern and correctly re-exports the ClauseConnector components for centralized access.

workspaces/ballerina/data-mapper/src/components/Diagram/Diagram.tsx (3)

39-39: LGTM!

The import addition enables ClauseConnectorNode integration in the diagram engine.


90-90: LGTM!

The factory registration follows the established pattern and enables the diagram engine to create and render ClauseConnectorNode instances.


161-164: LGTM!

The filter condition and type union correctly include ClauseConnectorNode, ensuring its position updates are handled alongside other connector node types.

workspaces/ballerina/data-mapper/src/components/Diagram/Port/model/InputOutputPortModel.ts (2)

23-23: LGTM!

The import addition is necessary for the new ArrayJoin mapping type handling.


78-80: LGTM!

The ArrayJoin handling correctly delegates to mapWithJoin and returns early, preventing the default createNewMapping flow. This aligns with the PR objective of adding JOIN clause support by opening the query clauses panel instead of creating a direct mapping.

workspaces/ballerina/data-mapper/src/components/Diagram/utils/port-utils.ts (1)

26-37: Typing update aligns with SubMappingNode usage.

Allowing SubMappingNode here keeps the port resolution path consistent with the new clause connectors.

workspaces/ballerina/data-mapper/src/components/Diagram/utils/modification-utils.ts (1)

176-203: JOIN helper integrates cleanly.

mapWithJoin wires the pending ArrayJoin flow into the clauses panel, so users get the dialog immediately with sensible defaults.

workspaces/ballerina/data-mapper/src/visitors/BaseVisitor.ts (1)

19-38: Query visit hooks look good.

The new optional callbacks extend the visitor contract without breaking implementers.

workspaces/ballerina/data-mapper/src/visitors/IntermediateNodeInitVisitor.ts (1)

18-50: Clause connector initialization is consistent.

Creating a ClauseConnectorNode during query traversal keeps intermediate nodes in sync with the new JOIN UI.

workspaces/ballerina/data-mapper/src/components/Diagram/LinkState/CreateLinkState.ts (1)

33-188: Link-state tweaks accommodate ClauseConnector nodes.

Forwarding intermediate ports to ClauseConnectorNode.targetMappedPort ensures JOIN connectors behave like existing link connectors.

workspaces/ballerina/ballerina-extension/src/rpc-managers/data-mapper/utils.ts (1)

456-611: Focus root tracking fits the new JOIN UX.

Populating focusInputRootMap while traversing arrays gives the front-end enough context to highlight source roots after JOIN setup.

workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClauseEditor.tsx (1)

23-164: JOIN form fields are thoughtfully added.

Including LHS/RHS expressions plus a default alias makes the JOIN workflow ready for immediate user input.

@KCSAbeywickrama KCSAbeywickrama deleted the bi-dm-join-clause branch November 19, 2025 11:28
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.

Frontend changes to add support for the join clause

2 participants