All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.table.explain.PlanJsonParser Maven / Gradle / Ivy

Go to download

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.flink.table.explain;

import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.DeserializationFeature;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.PropertyNamingStrategy;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * Utility for converting an execution plan from JSON to a human-readable string.
 */
public class PlanJsonParser {

	public static String getSqlExecutionPlan(String t, Boolean extended) throws Exception {
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

		// not every node is same, ignore the unknown field
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

		PlanTree tree = objectMapper.readValue(t, PlanTree.class);
		LinkedHashMap map = new LinkedHashMap<>();
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		int tabCount = 0;

		for (int index = 0; index < tree.getNodes().size(); index++) {
			Node tempNode = tree.getNodes().get(index);

			// input with operation such as join or union is coordinate, keep the same indent
			if ((tempNode.getPact().equals("Data Source")) && (map.containsKey(tempNode.getPact()))) {
				tabCount = map.get(tempNode.getPact());
			}
			else {
				map.put(tempNode.getPact(), tabCount);
			}

			printTab(tabCount, pw);
			pw.print("Stage " + tempNode.getId() + " : " + tempNode.getPact() + "\n");

			printTab(tabCount + 1, pw);
			String content = tempNode.getContents();

			// drop the hashcode of object instance
			int dele = tempNode.getContents().indexOf("@");
			if (dele > -1) {
				content = tempNode.getContents().substring(0, dele);
			}

			// replace with certain content if node is dataSource to pass
			// unit tests, because java and scala use different api to
			// get input element
			if (tempNode.getPact().equals("Data Source")) {
				content = "collect elements with CollectionInputFormat";
			}
			pw.print("content : " + content + "\n");

			List predecessors = tempNode.getPredecessors();
			if (predecessors != null) {
				printTab(tabCount + 1, pw);
				pw.print("ship_strategy : " + predecessors.get(0).getShipStrategy() + "\n");

				String mode = predecessors.get(0).getExchangeMode();
				if (mode != null) {
					printTab(tabCount + 1, pw);
					pw.print("exchange_mode : " + mode + "\n");
				}
			}

			if (tempNode.getDriverStrategy() != null) {
				printTab(tabCount + 1, pw);
				pw.print("driver_strategy : " + tempNode.getDriverStrategy() + "\n");
			}

			if (tempNode.getGlobalProperties() != null) {
				printTab(tabCount + 1, pw);
				pw.print(tempNode.getGlobalProperties().get(0).getName() + " : "
					+ tempNode.getGlobalProperties().get(0).getValue() + "\n");
			}

			if (extended) {
				List globalProperties = tempNode.getGlobalProperties();
				for (int i = 1; i < globalProperties.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(globalProperties.get(i).getName() + " : "
					+ globalProperties.get(i).getValue() + "\n");
				}

				List localProperties = tempNode.getLocalProperties();
				for (int i = 0; i < localProperties.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(localProperties.get(i).getName() + " : "
					+ localProperties.get(i).getValue() + "\n");
				}

				List estimates = tempNode.getEstimates();
				for (int i = 0; i < estimates.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(estimates.get(i).getName() + " : "
					+ estimates.get(i).getValue() + "\n");
				}

				List costs = tempNode.getCosts();
				for (int i = 0; i < costs.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(costs.get(i).getName() + " : "
					+ costs.get(i).getValue() + "\n");
				}

				List compilerHints = tempNode.getCompilerHints();
				for (int i = 0; i < compilerHints.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(compilerHints.get(i).getName() + " : "
					+ compilerHints.get(i).getValue() + "\n");
				}
			}
			tabCount++;
			pw.print("\n");
		}
		pw.close();
		return sw.toString();
	}

	private static void printTab(int tabCount, PrintWriter pw) {
		for (int i = 0; i < tabCount; i++) {
			pw.print("\t");
		}
	}
}

class PlanTree {
	private List nodes;

	public List getNodes() {
		return nodes;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy