gortiz commented on code in PR #13733: URL: https://github.com/apache/pinot/pull/13733#discussion_r1771372620
########## pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/LeafStageTransferableBlockOperator.java: ########## @@ -270,6 +276,69 @@ private TransferableBlock constructMetadataBlock() { return TransferableBlockUtils.getEndOfStreamTransferableBlock(multiStageQueryStats); } + public ExplainedNode explain() { + Preconditions.checkState(_requests.stream() + .allMatch(request -> request.getQueryContext().getExplain() == ExplainMode.NODE), + "All requests must have explain mode set to ExplainMode.NODE"); + + if (_executionFuture == null) { + _executionFuture = startExecution(); + } + + List<PlanNode> childNodes = new ArrayList<>(); + while (true) { + BaseResultsBlock resultsBlock; + try { + long timeout = _context.getDeadlineMs() - System.currentTimeMillis(); + resultsBlock = _blockingQueue.poll(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for results block", e); + } + if (resultsBlock == null) { + throw new RuntimeException("Timed out waiting for results block"); + } + // Terminate when receiving exception block + Map<Integer, String> exceptions = _exceptions; + if (exceptions != null) { + throw new RuntimeException("Received exception block: " + exceptions); + } + if (_isEarlyTerminated || resultsBlock == LAST_RESULTS_BLOCK) { + break; + } else if (!(resultsBlock instanceof ExplainV2ResultBlock)) { + throw new IllegalArgumentException("Expected ExplainV2ResultBlock, got: " + resultsBlock.getClass().getName()); + } else { + ExplainV2ResultBlock block = (ExplainV2ResultBlock) resultsBlock; + for (ExplainInfo physicalPlan : block.getPhysicalPlans()) { + childNodes.add(asNode(physicalPlan)); + } + } + } + String tableName = _context.getStageMetadata().getTableName(); + Map<String, Plan.ExplainNode.AttributeValue> attributes; + if (tableName == null) { // this should never happen, but let's be paranoid to never fail + attributes = Collections.emptyMap(); + } else { + attributes = Collections.singletonMap("table", Plan.ExplainNode.AttributeValue.newBuilder() + .setString(tableName) + .setMergeType(Plan.ExplainNode.AttributeValue.MergeType.IDEMPOTENT) Review Comment: No, the default is _DEFAULT_ :laughing:. But you are right, semantically is the same for Strings and given how GRPC works, it would reduce a couple of bytes per operator -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org