Skip to content

Conversation

pramodsatya
Copy link
Contributor

@pramodsatya pramodsatya commented Sep 11, 2025

Description

Adds module presto-main-tests to refactor scalar function tests from presto-main-base, so they can be extended into presto-native-tests and run with the native worker.
Rewrites queries from Presto java scalar function tests from select array_sort(ARRAY [5, 20]) to select array_sort(arg0) from (values (ARRAY [5, 20])) t(arg0). This ensures the query runs on C++ workers and is not constant folded on the coordinator.

Motivation and Context

Extend existing function tests from Presto to run with native worker. Currently only array_sort and array_except tests are refactored. The remaining tests will be refactored in follow-up PRs.

Impact

Improved function test coverage for Presto C++.

Test Plan

Added tests.

== NO RELEASE NOTE ==

@prestodb-ci prestodb-ci added the from:IBM PR from IBM label Sep 11, 2025
Copy link
Contributor

sourcery-ai bot commented Sep 11, 2025

Reviewer's Guide

Introduce a new scalar function test framework in presto-main-tests, refactor existing Java tests to use this abstraction, update Maven configurations to include the new module, and add a native test harness with projection rewriting for running tests on C++ workers.

Class diagram for refactored scalar function tests

classDiagram
    class AbstractTestArraySort {
        +void testArraySort()
    }
    class AbstractTestArrayExcept {
        +void testArrayExcept()
    }
    class TestFunctions {
        +void testFunctions()
    }
    class AbstractTestNativeFunctions {
        +void testNativeFunctions()
    }
    class TestArraySortFunction {
        +void testArraySortNative()
    }
    class TestArrayExceptFunction {
        +void testArrayExceptNative()
    }
    AbstractTestArraySort <|-- TestArraySortFunction
    AbstractTestArrayExcept <|-- TestArrayExceptFunction
    AbstractTestNativeFunctions <|-- TestArraySortFunction
    AbstractTestNativeFunctions <|-- TestArrayExceptFunction
    TestFunctions <|-- AbstractTestArraySort
    TestFunctions <|-- AbstractTestArrayExcept
Loading

File-Level Changes

Change Details Files
Add new test framework module for scalar functions
  • Introduce TestFunctions interface as the contract for function assertions
  • Add AbstractTestArrayExcept and AbstractTestArraySort interfaces with default test methods
  • Create presto-main-tests POM to define the new module and its dependencies
presto-main-tests/src/main/java/com/facebook/presto/tests/operator/scalar/TestFunctions.java
presto-main-tests/src/main/java/com/facebook/presto/tests/operator/scalar/AbstractTestArrayExcept.java
presto-main-tests/src/main/java/com/facebook/presto/tests/operator/scalar/AbstractTestArraySort.java
presto-main-tests/pom.xml
Refactor existing base tests to leverage the new framework
  • Remove inline @test methods from TestArrayExceptFunction and TestArraySortFunction
  • Have those classes implement the corresponding abstract test interfaces
  • Update AbstractTestFunctions to implement TestFunctions and add assertFunctionNoRewrite
presto-main-base/src/test/java/com/facebook/presto/operator/scalar/TestArrayExceptFunction.java
presto-main-base/src/test/java/com/facebook/presto/operator/scalar/TestArraySortFunction.java
presto-main-base/src/test/java/com/facebook/presto/operator/scalar/AbstractTestFunctions.java
Update Maven configurations to include and depend on presto-main-tests
  • Add presto-main-tests to the root modules list
  • Declare a test-jar dependency on presto-main-tests in multiple submodule POMs
pom.xml
presto-pinot/pom.xml
presto-hive/pom.xml
presto-i18n-functions/pom.xml
presto-main-base/pom.xml
presto-ml/pom.xml
presto-native-execution/pom.xml
presto-native-tests/pom.xml
presto-teradata-functions/pom.xml
presto-iceberg/pom.xml
Introduce native test harness with projection rewriting
  • Add AbstractTestNativeFunctions to set up native QueryRunner and rewrite projections
  • Implement native TestArrayExceptFunction and TestArraySortFunction delegating to abstract tests
presto-native-tests/src/test/java/com/facebook/presto/nativetests/operator/scalar/AbstractTestNativeFunctions.java
presto-native-tests/src/test/java/com/facebook/presto/nativetests/operator/scalar/TestArrayExceptFunction.java
presto-native-tests/src/test/java/com/facebook/presto/nativetests/operator/scalar/TestArraySortFunction.java

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@pramodsatya pramodsatya changed the title [DNR][WIP] Add array function tests to native-tests Add scalar function tests to native-tests Sep 26, 2025
@pramodsatya pramodsatya marked this pull request as ready for review September 26, 2025 20:40
@prestodb-ci prestodb-ci requested review from a team, Mariamalmesfer and jkhaliqi and removed request for a team September 26, 2025 20:40
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `presto-main-tests/src/main/java/com/facebook/presto/tests/operator/scalar/AbstractTestArraySort.java:37` </location>
<code_context>
+        assertFunction("array_sort(reverse(sequence(-4, 3)))", new ArrayType(BIGINT),
+                asList(-4L, -3L, -2L, -1L, 0L, 1L, 2L, 3L));
+        assertFunction("repeat(1,4)", new ArrayType(INTEGER), asList(1, 1, 1, 1));
+        assertFunctionNoRewrite("cast(array[] as array<int>)", new ArrayType(INTEGER), asList());
+    }
+
</code_context>

<issue_to_address>
**suggestion (testing):** Suggestion: Add tests for array_sort on arrays containing only nulls and arrays with mixed nulls and values.

Please add tests for array_sort with arrays such as ARRAY[null, null] and ARRAY[1, null, 2] to verify correct null handling.

```suggestion
        assertFunction("repeat(1,4)", new ArrayType(INTEGER), asList(1, 1, 1, 1));
        // Test array_sort with only nulls
        assertFunction("array_sort(ARRAY [null, null])", new ArrayType(INTEGER), asList(null, null));
        // Test array_sort with mixed nulls and values
        assertFunction("array_sort(ARRAY [1, null, 2])", new ArrayType(INTEGER), asList(1, 2, null));
```
</issue_to_address>

### Comment 2
<location> `presto-main-tests/src/main/java/com/facebook/presto/tests/operator/scalar/AbstractTestArrayExcept.java:34-42` </location>
<code_context>
-        assertFunction("array_except(ARRAY[1, 5, 3], ARRAY[3])", new ArrayType(INTEGER), ImmutableList.of(1, 5));
-        assertFunction("array_except(ARRAY[CAST(1 as BIGINT), 5, 3], ARRAY[5])", new ArrayType(BIGINT), ImmutableList.of(1L, 3L));
-        assertFunction("array_except(ARRAY[CAST('x' as VARCHAR), 'y', 'z'], ARRAY['x'])", new ArrayType(VARCHAR), ImmutableList.of("y", "z"));
-        assertFunction("array_except(ARRAY[true, false, null], ARRAY[true])", new ArrayType(BOOLEAN), asList(false, null));
-        assertFunction("array_except(ARRAY[1.1E0, 5.4E0, 3.9E0], ARRAY[5, 5.4E0])", new ArrayType(DOUBLE), ImmutableList.of(1.1, 3.9));
-    }
</code_context>

<issue_to_address>
**suggestion (testing):** Suggestion: Add tests for array_except with arrays containing only nulls and arrays with all elements removed.

Please add tests for cases where input arrays contain only nulls, and where all elements are removed, to ensure these edge cases are handled correctly.

```suggestion
    @Test
    default void testBasic()
    {
        assertFunction("array_except(ARRAY[1, 5, 3], ARRAY[3])", new ArrayType(INTEGER), ImmutableList.of(1, 5));
        assertFunction("array_except(ARRAY[CAST(1 as BIGINT), 5, 3], ARRAY[5])", new ArrayType(BIGINT), ImmutableList.of(1L, 3L));
        assertFunction("array_except(ARRAY[CAST('x' as VARCHAR), 'y', 'z'], ARRAY['x'])", new ArrayType(VARCHAR), ImmutableList.of("y", "z"));
        assertFunction("array_except(ARRAY[true, false, null], ARRAY[true])", new ArrayType(BOOLEAN), asList(false, null));
        assertFunction("array_except(ARRAY[1.1E0, 5.4E0, 3.9E0], ARRAY[5, 5.4E0])", new ArrayType(DOUBLE), ImmutableList.of(1.1, 3.9));

        // Edge case: input arrays containing only nulls
        assertFunction("array_except(ARRAY[null, null], ARRAY[null])", new ArrayType(UNKNOWN), ImmutableList.of());
        assertFunction("array_except(ARRAY[null], ARRAY[null])", new ArrayType(UNKNOWN), ImmutableList.of());
        assertFunction("array_except(ARRAY[null, null], ARRAY[])", new ArrayType(UNKNOWN), asList((Object) null, null));

        // Edge case: all elements removed
        assertFunction("array_except(ARRAY[1, 2, 3], ARRAY[1, 2, 3])", new ArrayType(INTEGER), ImmutableList.of());
        assertFunction("array_except(ARRAY['a', 'b'], ARRAY['a', 'b'])", new ArrayType(VARCHAR), ImmutableList.of());
        assertFunction("array_except(ARRAY[true, false], ARRAY[true, false])", new ArrayType(BOOLEAN), ImmutableList.of());
    }
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@pramodsatya
Copy link
Contributor Author

@aditi-pandit, could you help review this change? IpAddress tests will be added to native-tests in a follow-up PR once this change is in. cc: @wongquijote

Copy link
Contributor

@aditi-pandit aditi-pandit left a comment

Choose a reason for hiding this comment

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

@pramodsatya : Thanks for this code. Had a high-level question. All these tests are on constant values... So is the reasoning for the rewrite to ensure these functions happen on the worker. Then I don't follow why we don't do that for all the tests and why some call the noRewrite function variation ?

@pramodsatya
Copy link
Contributor Author

@pramodsatya : Thanks for this code. Had a high-level question. All these tests are on constant values... So is the reasoning for the rewrite to ensure these functions happen on the worker. Then I don't follow why we don't do that for all the tests and why some call the noRewrite function variation ?

Thanks @aditi-pandit; yes, the rewrite will ensure these function calls will run on the native workers when run in native-tests. For certain function calls that will result in an error when run on native worker, or that cannot be rewritten, we are avoiding the rewrite:

  1. array_except(ARRAY[NULL], NULL): will fail on native worker with error VeloxRuntimeError: not a known type kind: UNKNOWN, unless query is rewritten so NULL constants have a type. Instead of modifying all queries in testNull which will fail with this error, it would be simpler to let such queries be folded on the coordinator. What do you think?
  2. cast(array[] as array<int>): although it is in testArraySort, this is unrelated to array_sort and cannot be rewritten. So it would be better to let it be evaluated on the coordinator. Would that be fine?

@aditi-pandit
Copy link
Contributor

aditi-pandit commented Sep 27, 2025

@pramodsatya : Thanks for this code. Had a high-level question. All these tests are on constant values... So is the reasoning for the rewrite to ensure these functions happen on the worker. Then I don't follow why we don't do that for all the tests and why some call the noRewrite function variation ?

Thanks @aditi-pandit; yes, the rewrite will ensure these function calls will run on the native workers when run in native-tests. For certain function calls that will result in an error when run on native worker, or that cannot be rewritten, we are avoiding the rewrite:

  1. array_except(ARRAY[NULL], NULL): will fail on native worker with error VeloxRuntimeError: not a known type kind: UNKNOWN, unless query is rewritten so NULL constants have a type. Instead of modifying all queries in testNull which will fail with this error, it would be simpler to let such queries be folded on the coordinator. What do you think?
  2. cast(array[] as array<int>): although it is in testArraySort, this is unrelated to array_sort and cannot be rewritten. So it would be better to let it be evaluated on the coordinator. Would that be fine?

@pramodsatya It defeats the purpose of the test if we are letting the function evaluate on the co-ordinator. Its better to fail with the errors in native engine.

@pramodsatya
Copy link
Contributor Author

Thanks @aditi-pandit, yes I agree it would be better to let unsupported queries fail on native workers and assert error messages, updated the tests accordingly. Could you PTAL?

@pramodsatya pramodsatya changed the title Add scalar function tests to native-tests test(native): Add scalar function tests to native-tests Oct 2, 2025
Copy link
Contributor

@aditi-pandit aditi-pandit left a comment

Choose a reason for hiding this comment

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

Thanks @pramodsatya. This is looking much better. Just 2 more simple changes needed.


public interface TestFunctions
{
void assertFunction(String projection, Type expectedType, Object expected);
Copy link
Contributor

Choose a reason for hiding this comment

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

@pramodsatya : Please add a comment about what these functions do.

@pramodsatya
Copy link
Contributor Author

pramodsatya commented Oct 14, 2025

Thanks @pramodsatya. This is looking much better. Just 2 more simple changes needed.

Thanks @aditi-pandit, updated accordingly. Could you PTAL?

@aditi-pandit
Copy link
Contributor

@pramodsatya : Please can you fix the checkstyle violations.

int depth = 0;
boolean inSingleQuote = false;
int numArgs = 1;
for (int i = 0; i < argsString.length(); i++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This ensures that expressions at depth = 0 are not constant folded, but anything > depth = 0 is constant folded. So say f(5) is not constant folded, but f(g(5)) say is constant folded. That is alright, though you should document it. Or error here if there is such usage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing this out, documented the limitation and the intent of rewrite here.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants