Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions presto-clp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.facebook.presto</groupId>
<artifactId>presto-main</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.facebook.presto</groupId>
<artifactId>presto-main-base</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.facebook.presto.common.function.OperatorType;
import com.facebook.presto.common.type.DecimalType;
import com.facebook.presto.common.type.RowType;
import com.facebook.presto.common.type.TimestampType;
import com.facebook.presto.common.type.Type;
import com.facebook.presto.common.type.VarcharType;
import com.facebook.presto.plugin.clp.ClpColumnHandle;
Expand Down Expand Up @@ -57,12 +58,15 @@
import static com.facebook.presto.common.type.IntegerType.INTEGER;
import static com.facebook.presto.common.type.RealType.REAL;
import static com.facebook.presto.common.type.SmallintType.SMALLINT;
import static com.facebook.presto.common.type.TimestampType.TIMESTAMP;
import static com.facebook.presto.common.type.TimestampType.TIMESTAMP_MICROSECONDS;
import static com.facebook.presto.common.type.TinyintType.TINYINT;
import static com.facebook.presto.plugin.clp.ClpErrorCode.CLP_PUSHDOWN_UNSUPPORTED_EXPRESSION;
import static com.facebook.presto.spi.relation.SpecialFormExpression.Form.AND;
import static java.lang.Integer.parseInt;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
* A translator to translate Presto {@link RowExpression}s into:
Expand Down Expand Up @@ -256,8 +260,10 @@ private ClpExpression handleBetween(CallExpression node)
}

String variable = variableOpt.get();
String lowerBound = getLiteralString((ConstantExpression) second);
String upperBound = getLiteralString((ConstantExpression) third);
Type lowerBoundType = second.getType();
String lowerBound = tryEnsureNanosecondTimestamp(lowerBoundType, getLiteralString((ConstantExpression) second));
Type upperBoundType = third.getType();
String upperBound = tryEnsureNanosecondTimestamp(upperBoundType, getLiteralString((ConstantExpression) third));
String kql = String.format("%s >= %s AND %s <= %s", variable, lowerBound, variable, upperBound);
String metadataSqlQuery = metadataFilterColumns.contains(variable)
? String.format("\"%s\" >= %s AND \"%s\" <= %s", variable, lowerBound, variable, upperBound)
Expand Down Expand Up @@ -440,6 +446,7 @@ private ClpExpression buildClpExpression(
RowExpression originalNode)
{
String metadataSqlQuery = null;
literalString = tryEnsureNanosecondTimestamp(literalType, literalString);
if (operator.equals(EQUAL)) {
if (literalType instanceof VarcharType) {
return new ClpExpression(format("%s: \"%s\"", variableName, escapeKqlSpecialCharsForStringValue(literalString)));
Expand Down Expand Up @@ -914,9 +921,31 @@ public static boolean isClpCompatibleNumericType(Type type)
|| type.equals(TINYINT)
|| type.equals(DOUBLE)
|| type.equals(REAL)
|| type.equals(TIMESTAMP)
|| type.equals(TIMESTAMP_MICROSECONDS)
|| type instanceof DecimalType;
}

private static String tryEnsureNanosecondTimestamp(Type type, String literalString)
{
if (type == TIMESTAMP) {
return ensureNanosecondTimestamp(TIMESTAMP, literalString);
}
else if (type == TIMESTAMP_MICROSECONDS) {
return ensureNanosecondTimestamp(TIMESTAMP_MICROSECONDS, literalString);
}
return literalString;
}

private static String ensureNanosecondTimestamp(TimestampType type, String literalString)
{
long literalNumber = Long.parseLong(literalString);
long seconds = type.getEpochSecond(literalNumber);
long nanosecondFraction = type.getNanos(literalNumber);
long nanoseconds = SECONDS.toNanos(seconds) + nanosecondFraction;
return Long.toString(nanoseconds);
}

private static class SubstrInfo
{
String variableName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.presto.plugin.clp;

import com.facebook.presto.dispatcher.DispatchManager;
import com.facebook.presto.execution.QueryManager;
import com.facebook.presto.plugin.clp.metadata.ClpMetadataProvider;
import com.facebook.presto.plugin.clp.metadata.ClpMySqlMetadataProvider;
import com.facebook.presto.plugin.clp.mockdb.ClpMockMetadataDatabase;
import com.facebook.presto.plugin.clp.mockdb.table.ColumnMetadataTableRows;
import com.facebook.presto.spi.QueryId;
import com.facebook.presto.spi.plan.PlanNode;
import com.facebook.presto.spi.plan.PlanNodeId;
import com.facebook.presto.spi.plan.TableScanNode;
import com.facebook.presto.tests.DistributedQueryRunner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.intellij.lang.annotations.Language;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.Map;
import java.util.Optional;

import static com.facebook.presto.execution.QueryState.RUNNING;
import static com.facebook.presto.plugin.clp.ClpQueryRunner.createQueryRunner;
import static com.facebook.presto.plugin.clp.metadata.ClpSchemaTreeNodeType.Boolean;
import static com.facebook.presto.plugin.clp.metadata.ClpSchemaTreeNodeType.DateString;
import static com.facebook.presto.plugin.clp.metadata.ClpSchemaTreeNodeType.Float;
import static com.facebook.presto.plugin.clp.metadata.ClpSchemaTreeNodeType.Integer;
import static com.facebook.presto.plugin.clp.metadata.ClpSchemaTreeNodeType.VarString;
import static java.lang.String.format;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

@Test(singleThreaded = true)
public class TestClpPushDown
{
private static final String TABLE_NAME = "test_pushdown";
private static final Long TEST_TS_SECONDS_LOWER_BOUND = 1746003005L;
private static final Long TEST_TS_NANOSECONDS_LOWER_BOUND = 1746003005000000000L;
private static final Long TEST_TS_SECONDS_UPPER_BOUND = 1746003015L;
private static final Long TEST_TS_NANOSECONDS_UPPER_BOUND = 1746003015000000000L;

private ClpMockMetadataDatabase mockMetadataDatabase;
private DistributedQueryRunner queryRunner;
private QueryManager queryManager;
private DispatchManager dispatchManager;

@BeforeMethod
public void setUp()
throws Exception
{
mockMetadataDatabase = ClpMockMetadataDatabase
.builder()
.build();
mockMetadataDatabase.addTableToDatasetsTableIfNotExist(ImmutableList.of(TABLE_NAME));
mockMetadataDatabase.addColumnMetadata(ImmutableMap.of(TABLE_NAME, new ColumnMetadataTableRows(
ImmutableList.of(
"city.Name",
"city.Region.id",
"city.Region.Name",
"fare",
"isHoliday",
"ts"),
ImmutableList.of(
VarString,
Integer,
VarString,
Float,
Boolean,
DateString))));
ClpConfig config = new ClpConfig()
.setPolymorphicTypeEnabled(true)
.setMetadataDbUrl(mockMetadataDatabase.getUrl())
.setMetadataDbUser(mockMetadataDatabase.getUsername())
.setMetadataDbPassword(mockMetadataDatabase.getPassword())
.setMetadataTablePrefix(mockMetadataDatabase.getTablePrefix());
ClpMetadataProvider metadataProvider = new ClpMySqlMetadataProvider(config);
queryRunner = createQueryRunner(
mockMetadataDatabase.getUrl(),
mockMetadataDatabase.getUsername(),
mockMetadataDatabase.getPassword(),
mockMetadataDatabase.getTablePrefix(),
Optional.of(0),
Optional.empty());
queryManager = queryRunner.getCoordinator().getQueryManager();
dispatchManager = queryRunner.getCoordinator().getDispatchManager();
}

@AfterMethod
public void tearDown()
throws InterruptedException
{
long maxCleanUpTime = 5 * 1000L; // 5 seconds
long currentCleanUpTime = 0L;
while (!queryManager.getQueries().isEmpty() && currentCleanUpTime < maxCleanUpTime) {
Thread.sleep(1000L);
currentCleanUpTime += 1000L;
}
if (null != mockMetadataDatabase) {
mockMetadataDatabase.teardown();
}
}
Comment on lines +104 to +117
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Ensure queryRunner is closed during teardown.

queryRunner spins up threads and in-memory services; leaving it open after each test leaks resources across the suite. Close it (and null it out) once outstanding queries are drained, handling exceptions so failures remain debuggable.

         while (!queryManager.getQueries().isEmpty() && currentCleanUpTime < maxCleanUpTime) {
             Thread.sleep(1000L);
             currentCleanUpTime += 1000L;
         }
-        if (null != mockMetadataDatabase) {
+        try {
+            if (queryRunner != null) {
+                queryRunner.close();
+            }
+        }
+        catch (Exception e) {
+            fail("Failed to close queryRunner", e);
+        }
+        finally {
+            queryRunner = null;
+        }
+        if (mockMetadataDatabase != null) {
             mockMetadataDatabase.teardown();
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@AfterMethod
public void tearDown()
throws InterruptedException
{
long maxCleanUpTime = 5 * 1000L; // 5 seconds
long currentCleanUpTime = 0L;
while (!queryManager.getQueries().isEmpty() && currentCleanUpTime < maxCleanUpTime) {
Thread.sleep(1000L);
currentCleanUpTime += 1000L;
}
if (null != mockMetadataDatabase) {
mockMetadataDatabase.teardown();
}
}
@AfterMethod
public void tearDown()
throws InterruptedException
{
long maxCleanUpTime = 5 * 1000L; // 5 seconds
long currentCleanUpTime = 0L;
while (!queryManager.getQueries().isEmpty() && currentCleanUpTime < maxCleanUpTime) {
Thread.sleep(1000L);
currentCleanUpTime += 1000L;
}
try {
if (queryRunner != null) {
queryRunner.close();
}
}
catch (Exception e) {
fail("Failed to close queryRunner", e);
}
finally {
queryRunner = null;
}
if (mockMetadataDatabase != null) {
mockMetadataDatabase.teardown();
}
}
🤖 Prompt for AI Agents
In presto-clp/src/test/java/com/facebook/presto/plugin/clp/TestClpPushDown.java
around lines 104 to 117, the tearDown method drains outstanding queries but does
not close the queryRunner, which leaks threads and in-memory services; after
waiting for queries to drain, call queryRunner.close() inside a try/catch so any
exception is logged or rethrown for debuggability, then set queryRunner = null
to avoid reuse; do this before or after mockMetadataDatabase.teardown() as
appropriate and ensure exceptions are handled (logged) so test failures remain
debuggable.


public void testTimestampComparisons()
{
// Test logical binary
testPushDown(format("ts > from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND), format("ts > %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("ts >= from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND), format("ts >= %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("ts < from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND), format("ts < %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("ts <= from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND), format("ts <= %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("ts = from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND), format("ts: %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("ts != from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND), format("NOT ts: %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("ts <> from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND), format("NOT ts: %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("from_unixtime(%s) < ts", TEST_TS_SECONDS_LOWER_BOUND), format("ts > %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("from_unixtime(%s) <= ts", TEST_TS_SECONDS_LOWER_BOUND), format("ts >= %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("from_unixtime(%s) > ts", TEST_TS_SECONDS_LOWER_BOUND), format("ts < %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("from_unixtime(%s) >= ts", TEST_TS_SECONDS_LOWER_BOUND), format("ts <= %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("from_unixtime(%s) = ts", TEST_TS_SECONDS_LOWER_BOUND), format("ts: %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("from_unixtime(%s) != ts", TEST_TS_SECONDS_LOWER_BOUND), format("NOT ts: %s", TEST_TS_NANOSECONDS_LOWER_BOUND));
testPushDown(format("from_unixtime(%s) <> ts", TEST_TS_SECONDS_LOWER_BOUND), format("NOT ts: %s", TEST_TS_NANOSECONDS_LOWER_BOUND));

// Test BETWEEN
testPushDown(format("ts >= from_unixtime(%s) AND ts <= from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND, TEST_TS_SECONDS_UPPER_BOUND),
format("ts >= %s AND ts <= %s", TEST_TS_NANOSECONDS_LOWER_BOUND, TEST_TS_NANOSECONDS_UPPER_BOUND));
testPushDown(format("ts BETWEEN from_unixtime(%s) AND from_unixtime(%s)", TEST_TS_SECONDS_LOWER_BOUND, TEST_TS_SECONDS_UPPER_BOUND),
format("ts >= %s AND ts <= %s", TEST_TS_NANOSECONDS_LOWER_BOUND, TEST_TS_NANOSECONDS_UPPER_BOUND));
}

private void testPushDown(String filter, String expectedPushDown)
{
try {
QueryId id = queryRunner.getCoordinator().getDispatchManager().createQueryId();
@Language("SQL") String sql = format("SELECT * FROM clp.default.test_pushdown WHERE %s LIMIT 1", filter);
dispatchManager.createQuery(
id,
"slug",
0,
new TestingClpSessionContext(queryRunner.getDefaultSession()),
sql).get();
long maxDispatchingAndPlanningTime = 60 * 1000L; // 1 minute
long currentWaitingTime = 0L;
while (dispatchManager.getQueryInfo(id).getState().ordinal() != RUNNING.ordinal() && currentWaitingTime < maxDispatchingAndPlanningTime) {
Thread.sleep(1000L);
currentWaitingTime += 1000L;
}
assertTrue(currentWaitingTime < maxDispatchingAndPlanningTime);
Comment on lines +155 to +161
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider reducing the maximum wait time or making it configurable.

A 60-second maximum wait time for the query to reach RUNNING state seems excessive for unit tests and may slow down the test suite. Consider:

  1. Reducing the wait time to 10-15 seconds for faster feedback
  2. Making the timeout configurable via system property for different environments
  3. Adding more informative failure messages if the timeout is exceeded

Apply this diff to reduce the wait time and improve the error message:

-            long maxDispatchingAndPlanningTime = 60 * 1000L;    // 1 minute
+            long maxDispatchingAndPlanningTime = 15 * 1000L;    // 15 seconds
             long currentWaitingTime = 0L;
             while (dispatchManager.getQueryInfo(id).getState().ordinal() != RUNNING.ordinal() && currentWaitingTime < maxDispatchingAndPlanningTime) {
                 Thread.sleep(1000L);
                 currentWaitingTime += 1000L;
             }
-            assertTrue(currentWaitingTime < maxDispatchingAndPlanningTime);
+            assertTrue(currentWaitingTime < maxDispatchingAndPlanningTime, 
+                format("Query did not reach RUNNING state within %dms. Current state: %s", 
+                    maxDispatchingAndPlanningTime, dispatchManager.getQueryInfo(id).getState()));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
long maxDispatchingAndPlanningTime = 60 * 1000L; // 1 minute
long currentWaitingTime = 0L;
while (dispatchManager.getQueryInfo(id).getState().ordinal() != RUNNING.ordinal() && currentWaitingTime < maxDispatchingAndPlanningTime) {
Thread.sleep(1000L);
currentWaitingTime += 1000L;
}
assertTrue(currentWaitingTime < maxDispatchingAndPlanningTime);
long maxDispatchingAndPlanningTime = 15 * 1000L; // 15 seconds
long currentWaitingTime = 0L;
while (dispatchManager.getQueryInfo(id).getState().ordinal() != RUNNING.ordinal()
&& currentWaitingTime < maxDispatchingAndPlanningTime) {
Thread.sleep(1000L);
currentWaitingTime += 1000L;
}
assertTrue(
currentWaitingTime < maxDispatchingAndPlanningTime,
format(
"Query did not reach RUNNING state within %dms. Current state: %s",
maxDispatchingAndPlanningTime,
dispatchManager.getQueryInfo(id).getState()
)
);
🤖 Prompt for AI Agents
In presto-clp/src/test/java/com/facebook/presto/plugin/clp/TestClpPushDown.java
around lines 141-147, replace the hard-coded 60_000L timeout with a configurable
timeout (read a System property like "test.dispatch.timeoutMillis" and default
to 15_000L), use that value in the loop and waiting-time accumulation, and
update the final assertion to include a clear failure message showing the query
id, final state and elapsed wait time so failures are informative; ensure
parsing of the system property is safe with a fallback to the default.

boolean isPushDownGenerated = false;
for (Map.Entry<PlanNodeId, PlanNode> entry : queryManager.getFullQueryInfo(id).getPlanIdNodeMap().entrySet()) {
if (!(entry.getValue() instanceof TableScanNode)
|| (!(((TableScanNode) entry.getValue()).getTable().getLayout().orElse(null) instanceof ClpTableLayoutHandle))) {
continue;
}
ClpTableLayoutHandle clpTableLayoutHandle = (ClpTableLayoutHandle) ((TableScanNode) entry.getValue()).getTable().getLayout().orElseThrow(AssertionError::new);
String actualPushDown = clpTableLayoutHandle.getKqlQuery().orElse(null);
assertEquals(actualPushDown, expectedPushDown);
isPushDownGenerated = true;
break;
}
assertTrue(isPushDownGenerated);
Comment on lines +162 to +174
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Improve error handling for missing TableScanNode.

If no TableScanNode with a ClpTableLayoutHandle is found, the test fails with "isPushDownGenerated is false", which doesn't provide much context. Consider adding more informative error messages to help diagnose test failures.

Apply this diff to improve error reporting:

             boolean isPushDownGenerated = false;
+            StringBuilder debugInfo = new StringBuilder("Available plan nodes:\n");
             for (Map.Entry<PlanNodeId, PlanNode> entry : queryManager.getFullQueryInfo(id).getPlanIdNodeMap().entrySet()) {
+                debugInfo.append(format("  %s: %s%n", entry.getKey(), entry.getValue().getClass().getSimpleName()));
                 if (!(entry.getValue() instanceof TableScanNode)
                         || (!(((TableScanNode) entry.getValue()).getTable().getLayout().orElse(null) instanceof ClpTableLayoutHandle))) {
                     continue;
                 }
                 ClpTableLayoutHandle clpTableLayoutHandle = (ClpTableLayoutHandle) ((TableScanNode) entry.getValue()).getTable().getLayout().orElseThrow(AssertionError::new);
                 String actualPushDown = clpTableLayoutHandle.getKqlQuery().orElse(null);
                 assertEquals(actualPushDown, expectedPushDown);
                 isPushDownGenerated = true;
                 break;
             }
-            assertTrue(isPushDownGenerated);
+            assertTrue(isPushDownGenerated, 
+                format("No TableScanNode with ClpTableLayoutHandle found in query plan.%n%s", debugInfo));
             queryManager.cancelQuery(id);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
boolean isPushDownGenerated = false;
for (Map.Entry<PlanNodeId, PlanNode> entry : queryManager.getFullQueryInfo(id).getPlanIdNodeMap().entrySet()) {
if (!(entry.getValue() instanceof TableScanNode)
|| (!(((TableScanNode) entry.getValue()).getTable().getLayout().orElse(null) instanceof ClpTableLayoutHandle))) {
continue;
}
ClpTableLayoutHandle clpTableLayoutHandle = (ClpTableLayoutHandle) ((TableScanNode) entry.getValue()).getTable().getLayout().orElseThrow(AssertionError::new);
String actualPushDown = clpTableLayoutHandle.getKqlQuery().orElse(null);
assertEquals(actualPushDown, expectedPushDown);
isPushDownGenerated = true;
break;
}
assertTrue(isPushDownGenerated);
boolean isPushDownGenerated = false;
StringBuilder debugInfo = new StringBuilder("Available plan nodes:\n");
for (Map.Entry<PlanNodeId, PlanNode> entry : queryManager.getFullQueryInfo(id).getPlanIdNodeMap().entrySet()) {
debugInfo.append(format(" %s: %s%n", entry.getKey(), entry.getValue().getClass().getSimpleName()));
if (!(entry.getValue() instanceof TableScanNode)
|| !(((TableScanNode) entry.getValue()).getTable().getLayout().orElse(null) instanceof ClpTableLayoutHandle))) {
continue;
}
ClpTableLayoutHandle clpTableLayoutHandle =
(ClpTableLayoutHandle) ((TableScanNode) entry.getValue())
.getTable()
.getLayout()
.orElseThrow(AssertionError::new);
String actualPushDown = clpTableLayoutHandle.getKqlQuery().orElse(null);
assertEquals(actualPushDown, expectedPushDown);
isPushDownGenerated = true;
break;
}
assertTrue(isPushDownGenerated,
format("No TableScanNode with ClpTableLayoutHandle found in query plan.%n%s", debugInfo));
queryManager.cancelQuery(id);
🤖 Prompt for AI Agents
In presto-clp/src/test/java/com/facebook/presto/plugin/clp/TestClpPushDown.java
around lines 148 to 160, the test currently fails with an unhelpful
"isPushDownGenerated is false" when no TableScanNode with a ClpTableLayoutHandle
is found and uses assertEquals without context; update the test to throw/assert
with informative messages: when iterating, collect or detect absence and after
loop call fail(...) or assertTrue(..., "No TableScanNode with
ClpTableLayoutHandle found for query id=" + id) to include the query id and any
identifying info; also change the assertEquals to include an assertion message
showing expected and actual pushdown (e.g. assertEquals("Pushdown mismatch for
query id=" + id + ": expected=<" + expectedPushDown + "> actual=<" +
actualPushDown + ">", expectedPushDown, actualPushDown)) so failures give clear
diagnostics.

queryManager.cancelQuery(id);
}
catch (Exception e) {
fail(e.getMessage());
}
}
}
Loading
Loading