Skip to content

Conversation

@asifabashar
Copy link
Contributor

@asifabashar asifabashar commented Jan 2, 2026

Description

The transpose command outputs the requested number of search rows as columns, effectively transposing each result row into a corresponding column of field values. (Part of roadmap [https://github.com//issues/4287])
transpose [int] [column_name=]

Required Arguments: None.
Optional Arguments:

column_name
Syntax: column_name=

Description: The name of the first column to use when transposing rows. This column holds the field names.

Default: column

int
Syntax:

Description: Limit the number of rows to transpose.

Default: 5

Usage Notes:

When you use the transpose command, the field names in the output depend on the arguments provided.
By default, the field names are:
column, row 1, row 2, ...

Examples

  1. Transpose the results of a stats command

os> source=accounts | stats sum(age) by gender, state

sum(age) gender state
36 M TN
33 M MD
32 M IL
28 F VA

When you add the transpose command to the end of the search, the results look something like this:
os> source=accounts | stats sum(age) by gender, state | transpose

column row 1 row 2 row 3 row 4
sum(age) 36 33 32 28
gender M M M F
state TN MD IL VA

Related Issues

Resolves #4786

Check List

  • New functionality includes testing.
  • New functionality has been documented.
  • New functionality has javadoc added.
  • New functionality has a user manual doc added.
  • New PPL command checklist all confirmed.
  • API changes companion pull request created.
  • Commits are signed per the DCO using --signoff or -s.
  • Public documentation issue/PR created.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

asifabashar and others added 14 commits December 16, 2025 15:48
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

Adds a new end-to-end PPL transpose command: lexer/parser, AST node and builder, analyzer stub, Calcite planning implementation (unpivot then pivot), anonymizer support, documentation, expected explain output, and unit/integration tests.

Changes

Cohort / File(s) Summary
Parser & Lexer
ppl/src/main/antlr/OpenSearchPPLLexer.g4, ppl/src/main/antlr/OpenSearchPPLParser.g4
New TRANSPOSE and COLUMN_NAME tokens; added transposeCommand and transposeParameter grammar to parse optional numeric limit and optional column_name parameter; integrated into commands alternatives.
PPL AST & Builder
ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java, ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java
AstBuilder constructs Transpose AST node from parsed args; ArgumentFactory added getArgumentList for transpose parameters, validating number and column_name.
Core AST Node & Visitor
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java, core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java
New Transpose UnresolvedPlan with defaults (maxRows=5, columnName="column"), attach/getChild, validation and parsing; visitor method visitTranspose added delegating to children.
Analysis
core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
Added visitTranspose in Analyzer that currently throws a Calcite-only exception (explicitly restricts non-Calcite paths).
Calcite Planning
core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
New visitTranspose implementation: two-phase transformation—unpivot input rows into (row_id, column, value) using ROW_NUMBER, then pivot to wide layout using CASE/MAX aggregations up to maxRows; validates maxRows.
PPL Query Anonymizer
ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java
Added anonymization handling for Transpose, masking column_name and preserving child anonymization.
Docs
docs/category.json, docs/user/ppl/cmd/transpose.md, docs/user/ppl/index.md
Added documentation page and registered the transpose command in docs index and command table; included syntax, examples, and limitations.
Integration Tests
integ-test/.../CalciteTransposeCommandIT.java, integ-test/.../CalciteExplainIT.java, integ-test/.../CalciteNoPushdownIT.java, integ-test/.../CrossClusterSearchIT.java, integ-test/.../NewAddedCommandsIT.java
Added CalciteTransposeCommandIT and related integration tests (explain, cross-cluster, general PPL), and enabled test suite inclusion.
Unit & Calcite Tests
ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java, ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java
Added logical/physical plan and result assertions for transpose and anonymizer unit test.
Test Resources
integ-test/src/test/resources/expectedOutput/calcite/explain_transpose.yaml
Added expected explain output (logical + physical plans) for transpose explain tests.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Parser as PPL Parser
    participant AstBuilder
    participant Analyzer
    participant Calcite as CalciteRelNodeVisitor
    participant ES as OpenSearch Index

    User->>Parser: "source=... | transpose [n] [column_name=...]"
    Parser->>AstBuilder: parse transposeCommand
    AstBuilder->>AstBuilder: ArgumentFactory.getArgumentList()
    AstBuilder->>Analyzer: Transpose AST node
    Analyzer->>Calcite: visitTranspose(node, context)

    rect rgb(230,240,255)
      note over Calcite: Phase 1 — Unpivot (derive row_id using ROW_NUMBER)
      Calcite->>Calcite: unpivot fields -> (row_id, column, value)
    end

    rect rgb(230,255,235)
      note over Calcite: Phase 2 — Pivot (validate maxRows, build CASE/MAX aggregations)
      Calcite->>Calcite: pivot to columns: column, row1..rowN
      Calcite->>ES: execute translated query
    end

    ES-->>Calcite: results
    Calcite-->>User: transposed result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

PPL, feature, enhancement

Suggested reviewers

  • LantaoJin
  • penghuo
  • kavithacm
  • ps48
  • ykmr1224
  • joshuali925
  • derek-ho
  • anirudha
  • GumpacG
  • Swiddis

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description provides details about the transpose command functionality, syntax, usage examples, and references the related issue #4786, making it clearly related to the changeset.
Linked Issues check ✅ Passed The PR implements all key requirements from issue #4786: adds transpose command support, implements optional int and column_name parameters with correct defaults, provides proper syntax and examples, and includes tests and documentation.
Out of Scope Changes check ✅ Passed All changes are in scope and directly related to implementing the transpose command feature as specified in issue #4786, with no unrelated modifications.
Title check ✅ Passed The PR title clearly and specifically summarizes the main change: implementing the transpose command as specified in roadmap issue #4786.
✨ Finishing touches
  • 📝 Generate docstrings

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

@asifabashar asifabashar changed the title implment transpose command as in the roadmap #4786 implement transpose command as in the roadmap #4786 Jan 2, 2026
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: 2

🧹 Nitpick comments (17)
ppl/src/main/antlr/OpenSearchPPLParser.g4 (1)

332-339: Grammar allows duplicate parameters.

The transposeParameter* allows multiple parameters of the same type. For example, transpose 5 10 or transpose column_name='a' column_name='b' would be syntactically valid. Per the relevant code snippet from ArgumentFactory.getArgumentList, the implementation uses a Map<String, Argument> which would silently overwrite duplicates. Consider whether this is the desired behavior or if you want to detect and reject duplicate parameters with a clear error message.

core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (3)

10-10: Prefer explicit imports over wildcard import.

The wildcard import import lombok.*; could be replaced with explicit imports for better clarity and to avoid pulling in unused annotations.

-import lombok.*;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;

14-22: Consider removing @Setter for immutability.

Per coding guidelines, AST nodes should be immutable where possible. The @Setter annotation makes all fields mutable, but only child needs to be set via the attach() method (which is already implemented). Removing @Setter would make the arguments field effectively immutable after construction.

 @Getter
-@Setter
 @ToString
 @EqualsAndHashCode(callSuper = false)
 @RequiredArgsConstructor
 public class Transpose extends UnresolvedPlan {

24-35: Silent exception handling without logging.

The comment says "log warning and use default" but the catch block doesn't actually log anything. Either add proper logging or remove the misleading comment. Silent failures can make debugging difficult.

🔎 Proposed fix
   public Integer getMaxRows() {
-    Integer maxRows = 5;
+    int maxRows = 5;
     if (arguments.containsKey("number")) {
       try {
         maxRows = Integer.parseInt(arguments.get("number").getValue().toString());
       } catch (NumberFormatException e) {
-        // log warning and use default
-        maxRows = 5;
+        // Invalid number format, use default value of 5
       }
     }
     return maxRows;
   }
ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java (1)

250-255: Consider adding tests for edge cases.

The test covers the case with both arguments provided. Consider adding tests for other variations to ensure robust coverage:

  • transpose (no arguments, uses defaults)
  • transpose 10 (only number provided)
  • transpose column_name='col' (only column_name provided)
🔎 Example additional tests
@Test
public void testTransposeCommandDefaults() {
  assertEquals("source=table | transpose", anonymize("source=t | transpose"));
}

@Test
public void testTransposeCommandWithOnlyNumber() {
  assertEquals("source=table | transpose 10", anonymize("source=t | transpose 10"));
}

@Test
public void testTransposeCommandWithOnlyColumnName() {
  assertEquals(
      "source=table | transpose column_name=***",
      anonymize("source=t | transpose column_name='my_col'"));
}
core/src/main/java/org/opensearch/sql/analysis/Analyzer.java (1)

707-710: Verify exception message casing for consistency.

The exception message uses "Transpose" (capitalized). For consistency, verify whether Calcite exception messages in this codebase should be lowercase (as in "addtotals", line 529) or match the class name casing. Based on existing patterns, there's inconsistency across commands—consider standardizing.

ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java (1)

640-659: Consider using constants for masked values.

Two minor improvements for consistency:

  1. Line 652: When appending numberArg.getValue(), the code relies on toString() of the Literal object. For explicitness and type safety, consider extracting the primitive value:

    anonymized.append(StringUtils.format(" %s", numberArg.getValue().getValue()));
  2. Line 656: The hardcoded "***" should use the MASK_LITERAL constant (imported at line 11) for consistency with the rest of the codebase:

    anonymized.append(StringUtils.format(" %s=%s", "column_name", MASK_LITERAL));
🔎 Proposed refactor
     if (arguments.containsKey("number")) {
       Argument numberArg = arguments.get("number");
       if (numberArg != null) {
-        anonymized.append(StringUtils.format(" %s", numberArg.getValue()));
+        anonymized.append(StringUtils.format(" %s", numberArg.getValue().getValue()));
       }
     }
     if (arguments.containsKey("columnName")) {
-      anonymized.append(StringUtils.format(" %s=***", "column_name"));
+      anonymized.append(StringUtils.format(" %s=%s", "column_name", MASK_LITERAL));
     }
integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java (1)

205-214: Consider asserting the Calcite success path in testTransposeCommand

testTransposeCommand only exercises verifyQuery on the error path (when a ResponseException is thrown), mirroring other tests in this class. That means when Calcite is enabled and the query succeeds, this test doesn’t assert anything about the result for transpose.

If you want this IT to validate both modes, consider:

  • Capturing the successful executeQuery result when no exception is thrown, and
  • Calling verifyQuery(result) in both branches (or asserting non-empty datarows directly when isCalciteEnabled()).

This would make the test more robust while staying consistent with verifyQuery semantics.

ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java (1)

11-14: Add JavaDoc and tighten error messaging for transpose arguments

The new transpose argument helper looks correct, but a couple of polish items would help:

  • Line 313: getArgumentList(TransposeCommandContext ...) is public and lacks JavaDoc, whereas most other public getArgumentList overloads in this class are documented. A brief comment describing supported keys (number, columnName) and expected types would improve clarity.

  • Lines 319–322 & 329–332: The IllegalArgumentException messages are a bit rough (“COLUMN_NAME requires a string literal value”, “must be a int limit, column_name , got %s”). Consider making them more precise and user-friendly, e.g.:

    • "transpose COLUMN_NAME parameter requires a string literal value"
    • "A transpose parameter must be either an integer row limit or COLUMN_NAME=<string>, got: %s"

Functionally this is fine; these are just consistency/UX improvements. Based on learnings, keeping AST/argument helpers well-documented makes future grammar changes safer.

Also applies to: 313-335

core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java (1)

32-33: Transpose planning logic is sound; consider removing dead code and tightening the pipeline

The new visitTranspose implementation correctly:

  • Validates maxRows > 0.
  • Adds a ROW_NUMBER()-based __row_id__ to identify source rows.
  • Unpivots all fields into (columnName, value) rows with values cast to VARCHAR.
  • Re-pivots via MAX(CASE WHEN __row_id__ = i THEN value END) to produce row 1, row 2, …, row N columns grouped by columnName.

Two small improvements:

  1. Unused __row_pos__ window column

    Lines 769–778 compute rowPos (__row_pos__) with ROW_NUMBER() partitioned by columnName, but this column is never referenced afterwards. It’s also discarded implicitly by the final aggregate. You can drop this computation entirely:

  • RexNode rowPos =
  •    context
    
  •        .relBuilder
    
  •        .aggregateCall(SqlStdOperatorTable.ROW_NUMBER)
    
  •        .over()
    
  •        .partitionBy(context.relBuilder.field(columnName))
    
  •        .orderBy(context.relBuilder.field("__row_id__"))
    
  •        .rowsTo(RexWindowBounds.CURRENT_ROW)
    
  •        .as("__row_pos__");
    
  • context.relBuilder.projectPlus(rowPos);

2. **Optional: filter by `__row_id__ <= maxRows` before unpivot for efficiency**

Currently rows with `__row_id__ > maxRows` are ignored logically (their CASE expressions always return `NULL`), but they still flow through unpivot and aggregation. To reduce work when `maxRows` is small relative to the result set, you could insert a filter immediately after adding `__row_id__`:

```java
context.relBuilder.projectPlus(rowNumber);
context.relBuilder.filter(
    context.relBuilder.lessThanOrEqual(
        context.relBuilder.field("__row_id__"),
        context.relBuilder.literal(maxRows)));

This shouldn’t change semantics but will bound the amount of data processed by transpose.

Given the complexity of Calcite plans in this class, a brief JavaDoc or block comment on visitTranspose describing the two-phase UNPIVOT/PIVOT strategy would also help future readers. As per Calcite integration learnings, please re-run the existing transpose explain/result tests after any change to confirm plans still match expectations.

Also applies to: 700-802

ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java (1)

18-57: Good transpose coverage; add missing logical-plan assertion in testTransposeWithLimit

The new Calcite PPL tests give solid coverage of:

  • Simple aggregate + transpose.
  • Multiple aggregates with aliases.
  • Row-limit handling.
  • Custom column_name.

One small gap:

  • Lines 124–138: testTransposeWithLimit constructs an expectedLogical string but never calls verifyLogical(root, expectedLogical) (unlike the other tests). As a result, this test only checks result rows and Spark SQL, not the Calcite logical plan shape.

Consider adding:

verifyLogical(root, expectedLogical);

just after expectedLogical is built to keep plan verification consistent across all transpose tests.

Also applies to: 59-118, 120-165, 167-214

integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java (6)

18-24: Remove unused BANK index loading.

Line 23 loads Index.BANK, but none of the test methods use it. Remove this line to reduce unnecessary test setup overhead.

🔎 Proposed fix
  @Override
  public void init() throws Exception {
    super.init();
    enableCalcite();
    loadIndex(Index.ACCOUNT);
-   loadIndex(Index.BANK);
  }

27-30: Remove incomplete JavaDoc or make it complete.

The JavaDoc is incomplete: it has @throws IOException but no description of what the test does. Either remove the JavaDoc entirely (preferred for simple test methods) or add a proper description.

🔎 Proposed fix
-  /**
-   * default test without parameters on account index
-   *
-   * @throws IOException
-   */
   @Test
   public void testTranspose() throws IOException {

87-88: Fix misleading comment.

The comment "Should have original data plus one totals row" is misleading. The transpose command doesn't add a totals row; it transforms rows into columns. The comment should describe the transpose behavior instead.

🔎 Proposed fix
-    // Should have original data plus one totals row
-    var dataRows = result.getJSONArray("datarows");
+    // Get transposed data rows (fields become rows, original rows become columns)
+    var dataRows = result.getJSONArray("datarows");

160-161: Fix misleading comment.

The comment "Should have original data plus one totals row" is misleading. The transpose command doesn't add a totals row; it transforms rows into columns.

🔎 Proposed fix
-    // Should have original data plus one totals row
-    var dataRows = result.getJSONArray("datarows");
+    // Get transposed data rows (fields become rows, original rows become columns)
+    var dataRows = result.getJSONArray("datarows");

189-190: Fix misleading comment.

The comment "Should have original data plus one totals row" is misleading. The transpose command doesn't add a totals row; it transforms rows into columns.

🔎 Proposed fix
-    // Should have original data plus one totals row
-    var dataRows = result.getJSONArray("datarows");
+    // Get transposed data rows (fields become rows, original rows become columns)
+    var dataRows = result.getJSONArray("datarows");

31-198: Consider adding error condition tests.

The current test suite covers happy path scenarios well (default behavior, various limits, custom column name). Consider adding tests for error conditions such as:

  • Invalid transpose arguments (negative limits, invalid column names)
  • Transpose on empty result set
  • Transpose with very large limits

However, if these error conditions are tested elsewhere (e.g., in unit tests or other integration test files), this comment can be disregarded.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08be6f9 and 913ec30.

📒 Files selected for processing (20)
  • core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
  • core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java
  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
  • docs/category.json
  • docs/user/ppl/cmd/transpose.md
  • docs/user/ppl/index.md
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/resources/expectedOutput/calcite/explain_transpose.yaml
  • ppl/src/main/antlr/OpenSearchPPLLexer.g4
  • ppl/src/main/antlr/OpenSearchPPLParser.g4
  • ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
  • ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java
🧰 Additional context used
📓 Path-based instructions (13)
**/*.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

**/*.java: Use PascalCase for class names (e.g., QueryExecutor)
Use camelCase for method and variable names (e.g., executeQuery)
Use UPPER_SNAKE_CASE for constants (e.g., MAX_RETRY_COUNT)
Keep methods under 20 lines with single responsibility
All public classes and methods must have proper JavaDoc
Use specific exception types with meaningful messages for error handling
Prefer Optional<T> for nullable returns in Java
Avoid unnecessary object creation in loops
Use StringBuilder for string concatenation in loops
Validate all user inputs, especially queries
Sanitize data before logging to prevent injection attacks
Use try-with-resources for proper resource cleanup in Java
Maintain Java 11 compatibility when possible for OpenSearch 2.x
Document Calcite-specific workarounds in code

Files:

  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java
  • core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
  • core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java

⚙️ CodeRabbit configuration file

**/*.java: - Flag methods >50 lines as potentially too complex - suggest refactoring

  • Flag classes >500 lines as needing organization review
  • Check for dead code, unused imports, and unused variables
  • Identify code reuse opportunities across similar implementations
  • Assess holistic maintainability - is code easy to understand and modify?
  • Flag code that appears AI-generated without sufficient human review
  • Verify Java naming conventions (PascalCase for classes, camelCase for methods/variables)
  • Check for proper JavaDoc on public classes and methods
  • Flag redundant comments that restate obvious code
  • Ensure proper error handling with specific exception types
  • Check for Optional usage instead of null returns
  • Validate proper use of try-with-resources for resource management

Files:

  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java
  • core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
  • core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java
integ-test/**/*IT.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

End-to-end scenarios need integration tests in integ-test/ module

Files:

  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java

⚙️ CodeRabbit configuration file

integ-test/**/*IT.java: - Integration tests MUST use valid test data from resources

  • Verify test data files exist in integ-test/src/test/resources/
  • Check test assertions are meaningful and specific
  • Validate tests clean up resources after execution
  • Ensure tests are independent and can run in any order
  • Flag tests that reference non-existent indices (e.g., EMP)
  • Verify integration tests are in correct module (integ-test/)
  • Check tests can be run with ./gradlew :integ-test:integTest
  • Ensure proper test data setup and teardown
  • Validate end-to-end scenario coverage

Files:

  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
**/*IT.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

Name integration tests with *IT.java suffix in OpenSearch SQL

Files:

  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
**/test/**/*.java

⚙️ CodeRabbit configuration file

**/test/**/*.java: - Verify NULL input tests for all new functions

  • Check boundary condition tests (min/max values, empty inputs)
  • Validate error condition tests (invalid inputs, exceptions)
  • Ensure multi-document tests for per-document operations
  • Flag smoke tests without meaningful assertions
  • Check test naming follows pattern: test
  • Verify test data is realistic and covers edge cases
  • Verify test coverage for new business logic
  • Ensure tests are independent and don't rely on execution order
  • Validate meaningful test data that reflects real-world scenarios
  • Check for proper cleanup of test resources

Files:

  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
**/calcite/**/*.java

⚙️ CodeRabbit configuration file

**/calcite/**/*.java: - Follow existing Calcite integration patterns

  • Verify RelNode visitor implementations are complete
  • Check RexNode handling follows project conventions
  • Validate SQL generation is correct and optimized
  • Ensure Calcite version compatibility
  • Follow existing patterns in CalciteRelNodeVisitor and CalciteRexNodeVisitor
  • Document any Calcite-specific workarounds
  • Test compatibility with Calcite version constraints

Files:

  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
**/ppl/**/*.java

⚙️ CodeRabbit configuration file

**/ppl/**/*.java: - For PPL parser changes, verify grammar tests with positive/negative cases

  • Check AST generation for new syntax
  • Ensure corresponding AST builder classes are updated
  • Validate edge cases and boundary conditions

Files:

  • ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java
  • ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java
integ-test/src/test/resources/**/*

⚙️ CodeRabbit configuration file

integ-test/src/test/resources/**/*: - Verify test data is realistic and representative

  • Check data format matches expected schema
  • Ensure test data covers edge cases and boundary conditions

Files:

  • integ-test/src/test/resources/expectedOutput/calcite/explain_transpose.yaml
core/src/main/java/**/*.java

⚙️ CodeRabbit configuration file

core/src/main/java/**/*.java: - New functions MUST have unit tests in the same commit

  • Public methods MUST have JavaDoc with @param, @return, and @throws
  • Follow existing function implementation patterns in the same package
  • New expression functions should follow ExpressionFunction interface patterns
  • Validate function naming follows project conventions (camelCase)

Files:

  • core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
  • core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java
**/*Test.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

**/*Test.java: All new business logic requires unit tests
Name unit tests with *Test.java suffix in OpenSearch SQL

Files:

  • ppl/src/test/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizerTest.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java

⚙️ CodeRabbit configuration file

core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java: - Flag methods >50 lines - this file is known to be hard to read

  • Suggest extracting complex logic into helper methods
  • Check for code organization and logical grouping
  • Validate all RelNode types are handled

Files:

  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
**/*.g4

⚙️ CodeRabbit configuration file

**/*.g4: - Check if modifying unrelated grammar files (scope creep)

  • Verify grammar rule placement follows project patterns
  • Question if new rule needed vs reusing existing rules
  • Ensure changes are relevant to the PR's stated purpose

Files:

  • ppl/src/main/antlr/OpenSearchPPLParser.g4
  • ppl/src/main/antlr/OpenSearchPPLLexer.g4
ppl/src/main/antlr/OpenSearchPPLParser.g4

⚙️ CodeRabbit configuration file

ppl/src/main/antlr/OpenSearchPPLParser.g4: - Identify code reuse opportunities with existing commands

  • Validate command follows PPL naming and structure patterns
  • Check if command should be alias vs separate implementation

Files:

  • ppl/src/main/antlr/OpenSearchPPLParser.g4
core/src/main/java/org/opensearch/sql/ast/**/*.java

⚙️ CodeRabbit configuration file

core/src/main/java/org/opensearch/sql/ast/**/*.java: - AST nodes must be immutable where possible

  • Follow visitor pattern for AST traversal
  • Ensure proper toString() implementation for debugging

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
  • core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java
🧠 Learnings (8)
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Applies to **/*IT.java : Name integration tests with `*IT.java` suffix in OpenSearch SQL

Applied to files:

  • integ-test/src/test/java/org/opensearch/sql/security/CrossClusterSearchIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Test SQL generation and optimization paths for Calcite integration changes

Applied to files:

  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/resources/expectedOutput/calcite/explain_transpose.yaml
  • core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
📚 Learning: 2025-12-29T05:32:03.491Z
Learnt from: LantaoJin
Repo: opensearch-project/sql PR: 4993
File: opensearch/src/main/java/org/opensearch/sql/opensearch/planner/physical/CalciteEnumerableTopK.java:20-20
Timestamp: 2025-12-29T05:32:03.491Z
Learning: For any custom Calcite RelNode class (e.g., ones that extend EnumerableLimitSort or other Calcite RelNode types), always override the copy method. If copy is not overridden, cloning/copy operations may downgrade the instance to the parent class type, losing the custom behavior. In your implementation, ensure copy returns a new instance of the concrete class with all relevant fields and traits preserved, mirroring the current instance state.

Applied to files:

  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
📚 Learning: 2025-12-11T05:27:39.856Z
Learnt from: LantaoJin
Repo: opensearch-project/sql PR: 0
File: :0-0
Timestamp: 2025-12-11T05:27:39.856Z
Learning: In opensearch-project/sql, for SEMI and ANTI join types in CalciteRelNodeVisitor.java, the `max` option has no effect because these join types only use the left side to filter records based on the existence of matches in the right side. The join results are identical regardless of max value (max=1, max=2, or max=∞). The early return for SEMI/ANTI joins before processing the `max` option is intentional and correct behavior.

Applied to files:

  • integ-test/src/test/resources/expectedOutput/calcite/explain_transpose.yaml
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Follow existing patterns in `CalciteRelNodeVisitor` and `CalciteRexNodeVisitor` for Calcite integration

Applied to files:

  • core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
  • core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java
  • core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Applies to **/*.java : Document Calcite-specific workarounds in code

Applied to files:

  • integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java
  • ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTransposeTest.java
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Update corresponding AST builder classes when making PPL grammar changes

Applied to files:

  • ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java
  • ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: For PPL command PRs, refer docs/dev/ppl-commands.md and verify the PR satisfies the checklist

Applied to files:

  • docs/category.json
🧬 Code graph analysis (5)
ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java (1)
legacy/src/main/java/org/opensearch/sql/legacy/utils/StringUtils.java (1)
  • StringUtils (17-117)
integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java (2)
integ-test/src/test/java/org/opensearch/sql/ppl/PPLIntegTestCase.java (1)
  • PPLIntegTestCase (36-415)
integ-test/src/test/java/org/opensearch/sql/sql/IdentifierIT.java (1)
  • Index (218-262)
ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java (1)
ppl/src/main/java/org/opensearch/sql/ppl/utils/ArgumentFactory.java (1)
  • ArgumentFactory (41-449)
integ-test/src/test/java/org/opensearch/sql/ppl/NewAddedCommandsIT.java (1)
integ-test/src/test/java/org/opensearch/sql/legacy/TestUtils.java (1)
  • TestUtils (36-536)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (1)
core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java (1)
  • AbstractNodeVisitor (95-469)
🪛 LanguageTool
docs/user/ppl/cmd/transpose.md

[grammar] ~17-~17: Ensure spelling is correct
Context: ...ults This example shows transposing wihtout any parameters. It transforms 5 rows in...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~40-~40: Ensure spelling is correct
Context: ...-+-------+-------+ ``` ## Example 2: Tranpose results up to a provided number of rows...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~42-~42: Ensure spelling is correct
Context: ...rows. This example shows transposing wihtout any parameters. It transforms 4 rows in...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~65-~65: Ensure spelling is correct
Context: ...-+---------+-------+ ``` ## Example 2: Tranpose results up to a provided number of rows...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~67-~67: Ensure spelling is correct
Context: ...n name. This example shows transposing wihtout any parameters. It transforms 4 rows in...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: security-it-linux (25)
  • GitHub Check: security-it-linux (21)
  • GitHub Check: build-linux (25, integration)
  • GitHub Check: build-linux (21, doc)
  • GitHub Check: build-linux (21, integration)
  • GitHub Check: build-linux (25, doc)
  • GitHub Check: build-linux (21, unit)
  • GitHub Check: build-linux (25, unit)
  • GitHub Check: bwc-tests-full-restart (21)
  • GitHub Check: bwc-tests-full-restart (25)
  • GitHub Check: bwc-tests-rolling-upgrade (25)
  • GitHub Check: bwc-tests-rolling-upgrade (21)
  • GitHub Check: build-windows-macos (macos-14, 25, doc)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, integration)
  • GitHub Check: build-windows-macos (macos-14, 21, integration)
  • GitHub Check: build-windows-macos (macos-14, 25, integration)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (macos-14, 21, doc)
  • GitHub Check: build-windows-macos (macos-14, 21, unit)
  • GitHub Check: build-windows-macos (macos-14, 25, unit)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, integration)
  • GitHub Check: security-it-windows-macos (windows-latest, 25)
  • GitHub Check: security-it-windows-macos (macos-14, 25)
  • GitHub Check: security-it-windows-macos (windows-latest, 21)
  • GitHub Check: security-it-windows-macos (macos-14, 21)
  • GitHub Check: CodeQL-Scan (java)
  • GitHub Check: test-sql-cli-integration (21)
🔇 Additional comments (10)
docs/user/ppl/index.md (1)

83-83: Verify the "stable" status for a new command.

The transpose command is marked as stable (since 3.5), but most other recently introduced commands (e.g., rex, regex, spath, chart, streamstats) are marked as experimental in their initial release. Is this intentional, or should it follow the pattern of starting as experimental until the API stabilizes?

ppl/src/main/antlr/OpenSearchPPLParser.g4 (1)

1671-1672: LGTM!

Adding TRANSPOSE and COLUMN_NAME to searchableKeyWord allows these reserved words to be used as identifiers when needed, following the existing pattern for other command-related keywords.

integ-test/src/test/resources/expectedOutput/calcite/explain_transpose.yaml (1)

1-20: LGTM!

The expected explain output correctly captures both logical and physical plans for the transpose operation. The plan demonstrates the unpivot-pivot transformation strategy with appropriate CASE expressions, aggregations using MAX, and the LIMIT being pushed down to the index scan. The structure aligns with the CalciteRelNodeVisitor's visitTranspose implementation.

integ-test/src/test/java/org/opensearch/sql/calcite/CalciteNoPushdownIT.java (1)

106-106: LGTM!

The CalciteTransposeCommandIT.class is correctly added to the test suite in alphabetical order, ensuring transpose tests run in both pushdown-enabled and pushdown-disabled configurations.

ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java (1)

740-745: LGTM!

The visitTransposeCommand method correctly follows the established pattern of other command visitors, delegating argument parsing to ArgumentFactory and constructing the appropriate AST node. The implementation is concise and consistent with the codebase conventions. Based on learnings, this properly updates the corresponding AST builder classes when making PPL grammar changes.

docs/category.json (1)

46-46: LGTM!

The documentation reference is correctly added to the PPL CLI category list.

core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java (1)

286-288: LGTM!

The visitor method follows the established pattern and correctly delegates to visitChildren for AST traversal.

integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java (1)

2024-2034: Test follows existing Calcite explain patterns with proper plan validation.

Verified that the expected output file integ-test/src/test/resources/expectedOutput/calcite/explain_transpose.yaml exists and contains valid logical and physical plan definitions for the transpose operation with proper Calcite operators and execution nodes. Test correctly:

  • Enables pushdown for Calcite-specific behavior
  • Uses YAML comparison with ID ignoring for plan stability
  • References valid test data (opensearch-sql_test_index_account) with realistic query parameters
  • Follows test naming convention
ppl/src/main/antlr/OpenSearchPPLLexer.g4 (1)

49-49: Lexer additions for TRANSPOSE and COLUMN_NAME look consistent

The new TRANSPOSE and COLUMN_NAME tokens follow the existing naming/style conventions and are placed in appropriate sections of the lexer. No issues from a grammar/lexing perspective.

Also applies to: 74-75

integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteTransposeCommandIT.java (1)

53-57: The trailing spaces are intentional padding from the transpose command to align field names in columnar output—all field names are padded to 9 characters width ("firstname", "balance ", "age "). This is the expected behavior, confirmed by the source test data in accounts.json which contains unpadded field names. No action needed.

Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/user/ppl/index.md (1)

14-18: Add language specification to fenced code block.

The code fence on line 14 is missing a language specification. It should be ```ppl instead of ``` to comply with markdown linting rules (MD040) and maintain consistency with other code examples in the documentation.

If the original ppl ignore keyword was removed intentionally (e.g., to enable code rendering), consider using ```ppl with the language tag restored, or document the reason for the change.

🔎 Proposed fix
  for example, the following query retrieve firstname and lastname from accounts if age large than 18. 
  
-```
+```ppl
 source=accounts
 | where age > 18
 | fields firstname, lastname
-```
+```
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 913ec30 and 0ee8357.

📒 Files selected for processing (1)
  • docs/user/ppl/index.md
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Verify AST generation for new PPL parser syntax
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Update corresponding AST builder classes when making PPL grammar changes
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: For PPL command PRs, refer docs/dev/ppl-commands.md and verify the PR satisfies the checklist

Applied to files:

  • docs/user/ppl/index.md
🪛 markdownlint-cli2 (0.18.1)
docs/user/ppl/index.md

14-14: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: bwc-tests-full-restart (21)
  • GitHub Check: build-linux (25, integration)
  • GitHub Check: build-linux (25, doc)
  • GitHub Check: build-linux (21, doc)
  • GitHub Check: build-linux (25, unit)
  • GitHub Check: build-linux (21, integration)
  • GitHub Check: build-linux (21, unit)
  • GitHub Check: bwc-tests-rolling-upgrade (25)
  • GitHub Check: bwc-tests-full-restart (25)
  • GitHub Check: bwc-tests-rolling-upgrade (21)
  • GitHub Check: security-it-linux (21)
  • GitHub Check: security-it-linux (25)
  • GitHub Check: build-windows-macos (macos-14, 21, integration)
  • GitHub Check: build-windows-macos (macos-14, 21, unit)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, integration)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (macos-14, 25, integration)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, integration)
  • GitHub Check: build-windows-macos (macos-14, 25, unit)
  • GitHub Check: build-windows-macos (macos-14, 21, doc)
  • GitHub Check: build-windows-macos (macos-14, 25, doc)
  • GitHub Check: security-it-windows-macos (macos-14, 25)
  • GitHub Check: security-it-windows-macos (windows-latest, 21)
  • GitHub Check: security-it-windows-macos (macos-14, 21)
  • GitHub Check: security-it-windows-macos (windows-latest, 25)
  • GitHub Check: CodeQL-Scan (java)
  • GitHub Check: test-sql-cli-integration (21)
🔇 Additional comments (1)
docs/user/ppl/index.md (1)

81-83: Transpose command entry properly added to the commands table.

The new transpose command row is correctly formatted and integrated into the command reference table. Version alignment with other recently-added commands (addtotals, addcoltotals at 3.5) is consistent.

Please verify that the referenced documentation file docs/user/ppl/cmd/transpose.md exists and is properly linked in the documentation structure, and that docs/category.json has been updated to include the new transpose page under the PPL CLI category (as mentioned in the PR summary).

Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
@asifabashar
Copy link
Contributor Author

@LantaoJin Please review.

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: 2

♻️ Duplicate comments (1)
docs/user/ppl/cmd/transpose.md (1)

1-92: Documentation issues already flagged in previous review.

The typos and description inaccuracies on Lines 17, 40, 42, 65, and 67 have already been identified in the previous review comments (typos: "wihtout" → "without", "Tranpose" → "Transpose"; numbering: Example 3 mislabeled as Example 2; descriptions need updating to reflect actual parameters used).

Please address the suggestions from the previous review.

🧹 Nitpick comments (1)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (1)

24-24: Use UPPER_SNAKE_CASE for constant naming.

The constant max_limit should be renamed to MAX_LIMIT to follow Java naming conventions for constants.

🔎 Proposed fix
-  private static final int max_limit = 1000;
+  private static final int MAX_LIMIT = 1000;

And update the reference on Line 36:

-    if (maxRows > max_limit) {
+    if (maxRows > MAX_LIMIT) {
       throw new IllegalArgumentException(
-          StringUtils.format("Maximum limit to transpose is %s", max_limit));
+          StringUtils.format("Maximum limit to transpose is %s", MAX_LIMIT));
     }

As per coding guidelines, use UPPER_SNAKE_CASE for constants.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee8357 and 616f536.

📒 Files selected for processing (3)
  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
  • docs/user/ppl/cmd/transpose.md
  • docs/user/ppl/index.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

**/*.java: Use PascalCase for class names (e.g., QueryExecutor)
Use camelCase for method and variable names (e.g., executeQuery)
Use UPPER_SNAKE_CASE for constants (e.g., MAX_RETRY_COUNT)
Keep methods under 20 lines with single responsibility
All public classes and methods must have proper JavaDoc
Use specific exception types with meaningful messages for error handling
Prefer Optional<T> for nullable returns in Java
Avoid unnecessary object creation in loops
Use StringBuilder for string concatenation in loops
Validate all user inputs, especially queries
Sanitize data before logging to prevent injection attacks
Use try-with-resources for proper resource cleanup in Java
Maintain Java 11 compatibility when possible for OpenSearch 2.x
Document Calcite-specific workarounds in code

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java

⚙️ CodeRabbit configuration file

**/*.java: - Flag methods >50 lines as potentially too complex - suggest refactoring

  • Flag classes >500 lines as needing organization review
  • Check for dead code, unused imports, and unused variables
  • Identify code reuse opportunities across similar implementations
  • Assess holistic maintainability - is code easy to understand and modify?
  • Flag code that appears AI-generated without sufficient human review
  • Verify Java naming conventions (PascalCase for classes, camelCase for methods/variables)
  • Check for proper JavaDoc on public classes and methods
  • Flag redundant comments that restate obvious code
  • Ensure proper error handling with specific exception types
  • Check for Optional usage instead of null returns
  • Validate proper use of try-with-resources for resource management

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
core/src/main/java/**/*.java

⚙️ CodeRabbit configuration file

core/src/main/java/**/*.java: - New functions MUST have unit tests in the same commit

  • Public methods MUST have JavaDoc with @param, @return, and @throws
  • Follow existing function implementation patterns in the same package
  • New expression functions should follow ExpressionFunction interface patterns
  • Validate function naming follows project conventions (camelCase)

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
core/src/main/java/org/opensearch/sql/ast/**/*.java

⚙️ CodeRabbit configuration file

core/src/main/java/org/opensearch/sql/ast/**/*.java: - AST nodes must be immutable where possible

  • Follow visitor pattern for AST traversal
  • Ensure proper toString() implementation for debugging

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Verify AST generation for new PPL parser syntax
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Update corresponding AST builder classes when making PPL grammar changes
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: For PPL command PRs, refer docs/dev/ppl-commands.md and verify the PR satisfies the checklist

Applied to files:

  • docs/user/ppl/index.md
🧬 Code graph analysis (1)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (2)
core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java (1)
  • AbstractNodeVisitor (95-469)
legacy/src/main/java/org/opensearch/sql/legacy/utils/StringUtils.java (1)
  • StringUtils (17-117)
🪛 LanguageTool
docs/user/ppl/cmd/transpose.md

[grammar] ~17-~17: Ensure spelling is correct
Context: ...results This example shows transposing wihtout any parameters. It transforms 5 rows in...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~40-~40: Ensure spelling is correct
Context: ...---+-------+-------+ ``` ## Example 2: Tranpose results up to a provided number of rows...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~42-~42: Ensure spelling is correct
Context: ...f rows. This example shows transposing wihtout any parameters. It transforms 4 rows in...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~65-~65: Ensure spelling is correct
Context: ...-+---------+-------+ ``` ## Example 2: Tranpose results up to a provided number of rows...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~67-~67: Ensure spelling is correct
Context: ...n name. This example shows transposing wihtout any parameters. It transforms 4 rows in...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: build-linux (25, integration)
  • GitHub Check: build-linux (21, doc)
  • GitHub Check: build-linux (21, unit)
  • GitHub Check: build-linux (21, integration)
  • GitHub Check: build-linux (25, doc)
  • GitHub Check: build-linux (25, unit)
  • GitHub Check: bwc-tests-full-restart (21)
  • GitHub Check: bwc-tests-full-restart (25)
  • GitHub Check: bwc-tests-rolling-upgrade (25)
  • GitHub Check: bwc-tests-rolling-upgrade (21)
  • GitHub Check: security-it-linux (25)
  • GitHub Check: security-it-linux (21)
  • GitHub Check: build-windows-macos (macos-14, 25, integration)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (macos-14, 25, unit)
  • GitHub Check: build-windows-macos (macos-14, 21, doc)
  • GitHub Check: build-windows-macos (macos-14, 25, doc)
  • GitHub Check: build-windows-macos (macos-14, 21, integration)
  • GitHub Check: build-windows-macos (macos-14, 21, unit)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, integration)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, integration)
  • GitHub Check: security-it-windows-macos (windows-latest, 25)
  • GitHub Check: security-it-windows-macos (windows-latest, 21)
  • GitHub Check: security-it-windows-macos (macos-14, 25)
  • GitHub Check: security-it-windows-macos (macos-14, 21)
  • GitHub Check: test-sql-cli-integration (21)
  • GitHub Check: CodeQL-Scan (java)
🔇 Additional comments (2)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (1)

51-65: LGTM!

The attach(), getChild(), and accept() methods follow standard AST patterns correctly. The use of ImmutableList for returning children is good practice for maintaining immutability.

docs/user/ppl/index.md (1)

81-83: LGTM!

The new command entries for addtotals, addcoltotals, and transpose are correctly formatted and consistent with existing entries. Version numbering (3.5), status (stable), and descriptions are appropriate.

Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
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: 0

♻️ Duplicate comments (1)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (1)

26-41: Validate numeric bounds and avoid silent error handling.

The null check on line 28 addresses the NPE concern from the previous review. However, several validation issues remain:

  1. Missing validation: No check for negative or zero values of maxRows, which would be invalid.
  2. Silent error handling: The NumberFormatException catch (lines 31-34) silently falls back to the default, which may hide user input errors.
  3. Misleading comment: Line 32 mentions "log warning" but no logging occurs.

Consider validating that maxRows > 0 after parsing and either logging the error or throwing a descriptive IllegalArgumentException when parsing fails, so users receive clear feedback about invalid input.

🔎 Proposed fix
   public Integer getMaxRows() {
     Integer maxRows = 5;
     if (arguments.containsKey("number") && arguments.get("number").getValue() != null) {
       try {
         maxRows = Integer.parseInt(arguments.get("number").getValue().toString());
+        if (maxRows <= 0) {
+          throw new IllegalArgumentException("Transpose 'number' must be positive");
+        }
       } catch (NumberFormatException e) {
-        // log warning and use default
-        maxRows = 5;
+        throw new IllegalArgumentException(
+            StringUtils.format("Invalid number format for transpose: %s", 
+                arguments.get("number").getValue()));
       }
     }
-    if (maxRows > max_limit) {
+    if (maxRows > MAX_LIMIT) {
       throw new IllegalArgumentException(
-          StringUtils.format("Maximum limit to transpose is %s", max_limit));
+          StringUtils.format("Maximum limit to transpose is %s", MAX_LIMIT));
     }
     return maxRows;
   }
🧹 Nitpick comments (2)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (2)

24-24: Use UPPER_SNAKE_CASE for constant naming.

The constant max_limit should follow Java naming conventions for constants.

🔎 Proposed fix
-  private static final int max_limit = 1000;
+  private static final int MAX_LIMIT = 1000;

Update references in line 36 and 38:

-    if (maxRows > max_limit) {
+    if (maxRows > MAX_LIMIT) {
       throw new IllegalArgumentException(
-          StringUtils.format("Maximum limit to transpose is %s", max_limit));
+          StringUtils.format("Maximum limit to transpose is %s", MAX_LIMIT));

As per coding guidelines, constants should use UPPER_SNAKE_CASE.


22-22: Consider using ImmutableMap for defensive immutability.

While the arguments reference is final, the map itself is mutable. For better immutability guarantees, consider wrapping it in an ImmutableMap in the constructor.

🔎 Example approach
public class Transpose extends UnresolvedPlan {
  private final @NonNull ImmutableMap<String, Argument> arguments;
  
  public Transpose(java.util.Map<String, Argument> arguments) {
    this.arguments = ImmutableMap.copyOf(arguments);
  }
  // ... rest of class
}

As per coding guidelines, AST nodes should be immutable where possible. However, if the current pattern is consistent with other UnresolvedPlan nodes, this is optional.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 616f536 and 46d6b0b.

📒 Files selected for processing (1)
  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
🧰 Additional context used
📓 Path-based instructions (3)
**/*.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

**/*.java: Use PascalCase for class names (e.g., QueryExecutor)
Use camelCase for method and variable names (e.g., executeQuery)
Use UPPER_SNAKE_CASE for constants (e.g., MAX_RETRY_COUNT)
Keep methods under 20 lines with single responsibility
All public classes and methods must have proper JavaDoc
Use specific exception types with meaningful messages for error handling
Prefer Optional<T> for nullable returns in Java
Avoid unnecessary object creation in loops
Use StringBuilder for string concatenation in loops
Validate all user inputs, especially queries
Sanitize data before logging to prevent injection attacks
Use try-with-resources for proper resource cleanup in Java
Maintain Java 11 compatibility when possible for OpenSearch 2.x
Document Calcite-specific workarounds in code

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java

⚙️ CodeRabbit configuration file

**/*.java: - Flag methods >50 lines as potentially too complex - suggest refactoring

  • Flag classes >500 lines as needing organization review
  • Check for dead code, unused imports, and unused variables
  • Identify code reuse opportunities across similar implementations
  • Assess holistic maintainability - is code easy to understand and modify?
  • Flag code that appears AI-generated without sufficient human review
  • Verify Java naming conventions (PascalCase for classes, camelCase for methods/variables)
  • Check for proper JavaDoc on public classes and methods
  • Flag redundant comments that restate obvious code
  • Ensure proper error handling with specific exception types
  • Check for Optional usage instead of null returns
  • Validate proper use of try-with-resources for resource management

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
core/src/main/java/**/*.java

⚙️ CodeRabbit configuration file

core/src/main/java/**/*.java: - New functions MUST have unit tests in the same commit

  • Public methods MUST have JavaDoc with @param, @return, and @throws
  • Follow existing function implementation patterns in the same package
  • New expression functions should follow ExpressionFunction interface patterns
  • Validate function naming follows project conventions (camelCase)

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
core/src/main/java/org/opensearch/sql/ast/**/*.java

⚙️ CodeRabbit configuration file

core/src/main/java/org/opensearch/sql/ast/**/*.java: - AST nodes must be immutable where possible

  • Follow visitor pattern for AST traversal
  • Ensure proper toString() implementation for debugging

Files:

  • core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Verify AST generation for new PPL parser syntax
🧬 Code graph analysis (1)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (2)
core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java (1)
  • AbstractNodeVisitor (95-469)
legacy/src/main/java/org/opensearch/sql/legacy/utils/StringUtils.java (1)
  • StringUtils (17-117)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: security-it-linux (21)
  • GitHub Check: security-it-linux (25)
  • GitHub Check: build-linux (25, integration)
  • GitHub Check: build-linux (25, unit)
  • GitHub Check: build-linux (21, doc)
  • GitHub Check: build-linux (21, integration)
  • GitHub Check: build-linux (25, doc)
  • GitHub Check: build-linux (21, unit)
  • GitHub Check: bwc-tests-full-restart (25)
  • GitHub Check: bwc-tests-rolling-upgrade (21)
  • GitHub Check: bwc-tests-full-restart (21)
  • GitHub Check: bwc-tests-rolling-upgrade (25)
  • GitHub Check: build-windows-macos (macos-14, 25, doc)
  • GitHub Check: build-windows-macos (macos-14, 21, doc)
  • GitHub Check: build-windows-macos (macos-14, 21, unit)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (macos-14, 25, unit)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, integration)
  • GitHub Check: security-it-windows-macos (macos-14, 25)
  • GitHub Check: build-windows-macos (macos-14, 25, integration)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, integration)
  • GitHub Check: build-windows-macos (macos-14, 21, integration)
  • GitHub Check: security-it-windows-macos (macos-14, 21)
  • GitHub Check: security-it-windows-macos (windows-latest, 21)
  • GitHub Check: security-it-windows-macos (windows-latest, 25)
  • GitHub Check: CodeQL-Scan (java)
  • GitHub Check: test-sql-cli-integration (21)
🔇 Additional comments (5)
core/src/main/java/org/opensearch/sql/ast/tree/Transpose.java (5)

1-21: LGTM: Class structure follows AST node patterns.

The class correctly extends UnresolvedPlan, uses appropriate Lombok annotations, and follows the visitor pattern. Imports are necessary and well-organized.


43-49: LGTM: Null check addresses previous concern.

The null check on line 45 properly addresses the NPE concern from the previous review. The method now safely handles null values.


51-55: LGTM: Follows standard AST pattern.

The attach() method correctly implements the standard pattern for attaching child nodes.


57-60: LGTM: Correctly uses ImmutableList.

The method properly returns an immutable list and handles the null child case appropriately.


62-65: LGTM: Correctly implements visitor pattern.

The method properly delegates to the visitor's visitTranspose method, following the established AST visitor pattern.

@asifabashar asifabashar changed the title implement transpose command as in the roadmap #4786 [Feature] implement transpose command as in the roadmap #4786 Jan 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] implment transpose command as in the roadmap

2 participants