This is an automated email from the ASF dual-hosted git repository. richardstartin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push: new a46b05f8f6 print explain plan when integration test query fails to ease debugging (#10057) a46b05f8f6 is described below commit a46b05f8f6fc5b380cb54e83b4dad3f9adfaff90 Author: Richard Startin <richardstar...@apache.org> AuthorDate: Thu Jan 5 09:36:42 2023 +0000 print explain plan when integration test query fails to ease debugging (#10057) --- .../tests/ClusterIntegrationTestUtils.java | 67 ++++++++++++++++++---- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterIntegrationTestUtils.java b/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterIntegrationTestUtils.java index 52a27b4772..e8f4d143e2 100644 --- a/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterIntegrationTestUtils.java +++ b/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterIntegrationTestUtils.java @@ -41,6 +41,7 @@ import java.util.Map; import java.util.Properties; import java.util.Random; import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -625,7 +626,8 @@ public class ClusterIntegrationTestUtils { if (h2Value == null) { if (pinotNumRecordsSelected != 0) { throw new RuntimeException("No record selected in H2 but " + pinotNumRecordsSelected - + " records selected in Pinot"); + + " records selected in Pinot, explain plan: " + getExplainPlan(pinotQuery, brokerUrl, headers, + extraJsonProperties)); } // Skip further comparison @@ -644,8 +646,10 @@ public class ClusterIntegrationTestUtils { // Fuzzy compare expected value and actual value boolean error = fuzzyCompare(h2Value, brokerValue, connectionValue); if (error) { - throw new RuntimeException("Value: " + c + " does not match, expected: " + h2Value - + ", got broker value: " + brokerValue + ", got client value:" + connectionValue); + throw new RuntimeException( + "Value: " + c + " does not match, expected: " + h2Value + ", got broker value: " + brokerValue + + ", got client value:" + connectionValue + ", explain plan: " + getExplainPlan(pinotQuery, + brokerUrl, headers, extraJsonProperties)); } } } else { @@ -666,8 +670,10 @@ public class ClusterIntegrationTestUtils { String connectionValue = resultTableResultSet.getString(i, c); boolean error = fuzzyCompare(h2Value, brokerValue, connectionValue); if (error) { - throw new RuntimeException("Value: " + c + " does not match, expected: " + h2Value - + ", got broker value: " + brokerValue + ", got client value:" + connectionValue); + throw new RuntimeException( + "Value: " + c + " does not match, expected: " + h2Value + ", got broker value: " + brokerValue + + ", got client value:" + connectionValue + ", explain plan: " + getExplainPlan(pinotQuery, + brokerUrl, headers, extraJsonProperties)); } } if (!h2ResultSet.next()) { @@ -680,6 +686,47 @@ public class ClusterIntegrationTestUtils { } } + private static String getExplainPlan(String pinotQuery, String brokerUrl, @Nullable Map<String, String> headers, + @Nullable Map<String, String> extraJsonProperties) + throws Exception { + JsonNode explainPlanForResponse = + ClusterTest.postQuery("explain plan for " + pinotQuery, brokerUrl, headers, extraJsonProperties); + Map<Integer, String> nodesById = new TreeMap<>(); + JsonNode rows = explainPlanForResponse.get("resultTable").get("rows"); + int[] parentMapping = new int[rows.size()]; + for (int i = 0; i < rows.size(); i++) { + JsonNode row = rows.get(i); + int id = row.get(1).asInt(); + if (id > 0) { + parentMapping[id] = row.get(2).asInt(); + } + nodesById.put(id, row.get(0).asText()); + } + int[] depths = new int[rows.size()]; + for (Map.Entry<Integer, String> pair : nodesById.entrySet()) { + int depth = 0; + int id = pair.getKey(); + int parentId = id; + while (parentId > 0) { + depth++; + parentId = parentMapping[parentId]; + } + if (id > 0) { + depths[id] = depth; + } + } + StringBuilder explainPlan = new StringBuilder(); + for (Map.Entry<Integer, String> pair : nodesById.entrySet()) { + explainPlan.append('\n'); + int id = pair.getKey(); + for (int i = 0; id > 0 && i < depths[id]; i++) { + explainPlan.append('\t'); + } + explainPlan.append(pair.getValue()); + } + return explainPlan.toString(); + } + private static int getH2ExpectedValues(Set<String> expectedValues, List<String> expectedOrderByValues, ResultSet h2ResultSet, ResultSetMetaData h2MetaData, Collection<String> orderByColumns) throws SQLException { @@ -753,15 +800,13 @@ public class ClusterIntegrationTestUtils { private static void comparePinotResultsWithExpectedValues(Set<String> expectedValues, List<String> expectedOrderByValues, org.apache.pinot.client.ResultSet connectionResultSet, - Set<String> orderByColumns, String pinotQuery, String h2Query, int h2NumRows, - long pinotNumRecordsSelected) { + Set<String> orderByColumns, String pinotQuery, String h2Query, int h2NumRows, long pinotNumRecordsSelected) { int pinotNumRows = connectionResultSet.getRowCount(); // No record selected in H2 if (h2NumRows == 0) { if (pinotNumRows != 0) { - throw new RuntimeException( - "No record selected in H2 but number of records selected in Pinot: " + pinotNumRows); + throw new RuntimeException("No record selected in H2 but number of records selected in Pinot: " + pinotNumRows); } if (pinotNumRecordsSelected != 0) { @@ -826,8 +871,8 @@ public class ClusterIntegrationTestUtils { String actualOrderByValue = actualOrderByValueBuilder.toString(); // Check actual value in expected values set, skip comparison if query response is truncated by limit if ((!isLimitSet || limit > h2NumRows) && !expectedValues.contains(actualValue)) { - throw new RuntimeException("Selection result returned in Pinot but not in H2: " + actualValue - + ", " + expectedValues); + throw new RuntimeException( + "Selection result returned in Pinot but not in H2: " + actualValue + ", " + expectedValues); } if (!orderByColumns.isEmpty()) { // Check actual group value is the same as expected group value in the same order. --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org