/** * 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.hadoop.hive.ql.metadata.formatting; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringEscapeUtils; import org.apache.hadoop.hive.metastore.TableType; import org.apache.hadoop.hive.metastore.api.FieldSchema; import org.apache.hadoop.hive.metastore.api.Index; import org.apache.hadoop.hive.metastore.api.StorageDescriptor; import org.apache.hadoop.hive.ql.index.HiveIndex; import org.apache.hadoop.hive.ql.index.HiveIndex.IndexType; import org.apache.hadoop.hive.ql.metadata.Partition; import org.apache.hadoop.hive.ql.metadata.Table; import org.apache.hadoop.hive.ql.plan.DescTableDesc; import org.apache.hadoop.hive.ql.plan.ShowIndexesDesc; /** * This class provides methods to format table and index information. * */ public final class MetaDataFormatUtils { public static final String FIELD_DELIM = "\t"; public static final String LINE_DELIM = "\n"; private static final int DEFAULT_STRINGBUILDER_SIZE = 2048; private static final int ALIGNMENT = 20; private MetaDataFormatUtils() { } private static void formatColumnsHeader(StringBuilder columnInformation) { columnInformation.append("# "); // Easy for shell scripts to ignore formatOutput(getColumnsHeader(), columnInformation); columnInformation.append(LINE_DELIM); } public static String getAllColumnsInformation(List<FieldSchema> cols) { StringBuilder columnInformation = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE); formatColumnsHeader(columnInformation); formatAllFields(columnInformation, cols); return columnInformation.toString(); } public static String getAllColumnsInformation(List<FieldSchema> cols, List<FieldSchema> partCols) { StringBuilder columnInformation = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE); formatColumnsHeader(columnInformation); formatAllFields(columnInformation, cols); if ((partCols != null) && (!partCols.isEmpty())) { columnInformation.append(LINE_DELIM).append("# Partition Information") .append(LINE_DELIM); formatColumnsHeader(columnInformation); formatAllFields(columnInformation, partCols); } return columnInformation.toString(); } private static void formatAllFields(StringBuilder tableInfo, List<FieldSchema> cols) { for (FieldSchema col : cols) { formatFieldSchemas(tableInfo, col); } } public static String getAllColumnsInformation(Index index) { StringBuilder indexInfo = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE); List<String> indexColumns = new ArrayList<String>(); indexColumns.add(index.getIndexName()); indexColumns.add(index.getOrigTableName()); // index key names List<FieldSchema> indexKeys = index.getSd().getCols(); StringBuilder keyString = new StringBuilder(); boolean first = true; for (FieldSchema key : indexKeys) { if (!first) { keyString.append(", "); } keyString.append(key.getName()); first = false; } indexColumns.add(keyString.toString()); indexColumns.add(index.getIndexTableName()); // index type String indexHandlerClass = index.getIndexHandlerClass(); IndexType indexType = HiveIndex.getIndexTypeByClassName(indexHandlerClass); indexColumns.add(indexType.getName()); indexColumns.add(index.getParameters().get("comment")); formatOutput(indexColumns.toArray(new String[0]), indexInfo); return indexInfo.toString(); } /* Displaying columns unformatted for backward compatibility. */ public static String displayColsUnformatted(List<FieldSchema> cols) { StringBuilder colBuffer = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE); for (FieldSchema col : cols) { colBuffer.append(col.getName()); colBuffer.append(FIELD_DELIM); colBuffer.append(col.getType()); colBuffer.append(FIELD_DELIM); colBuffer.append(col.getComment() == null ? "" : col.getComment()); colBuffer.append(LINE_DELIM); } return colBuffer.toString(); } public static String getPartitionInformation(Partition part) { StringBuilder tableInfo = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE); // Table Metadata tableInfo.append(LINE_DELIM).append("# Detailed Partition Information").append(LINE_DELIM); getPartitionMetaDataInformation(tableInfo, part); // Storage information. if (part.getTable().getTableType() != TableType.VIRTUAL_VIEW) { tableInfo.append(LINE_DELIM).append("# Storage Information").append(LINE_DELIM); getStorageDescriptorInfo(tableInfo, part.getTPartition().getSd()); } return tableInfo.toString(); } public static String getTableInformation(Table table) { StringBuilder tableInfo = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE); // Table Metadata tableInfo.append(LINE_DELIM).append("# Detailed Table Information").append(LINE_DELIM); getTableMetaDataInformation(tableInfo, table); // Storage information. tableInfo.append(LINE_DELIM).append("# Storage Information").append(LINE_DELIM); getStorageDescriptorInfo(tableInfo, table.getTTable().getSd()); if (table.isView()) { tableInfo.append(LINE_DELIM).append("# View Information").append(LINE_DELIM); getViewInfo(tableInfo, table); } return tableInfo.toString(); } private static void getViewInfo(StringBuilder tableInfo, Table tbl) { formatOutput("View Original Text:", tbl.getViewOriginalText(), tableInfo); formatOutput("View Expanded Text:", tbl.getViewExpandedText(), tableInfo); } private static void getStorageDescriptorInfo(StringBuilder tableInfo, StorageDescriptor storageDesc) { formatOutput("SerDe Library:", storageDesc.getSerdeInfo().getSerializationLib(), tableInfo); formatOutput("InputFormat:", storageDesc.getInputFormat(), tableInfo); formatOutput("OutputFormat:", storageDesc.getOutputFormat(), tableInfo); formatOutput("Compressed:", storageDesc.isCompressed() ? "Yes" : "No", tableInfo); formatOutput("Num Buckets:", String.valueOf(storageDesc.getNumBuckets()), tableInfo); formatOutput("Bucket Columns:", storageDesc.getBucketCols().toString(), tableInfo); formatOutput("Sort Columns:", storageDesc.getSortCols().toString(), tableInfo); if (storageDesc.getSerdeInfo().getParametersSize() > 0) { tableInfo.append("Storage Desc Params:").append(LINE_DELIM); displayAllParameters(storageDesc.getSerdeInfo().getParameters(), tableInfo); } } private static void getTableMetaDataInformation(StringBuilder tableInfo, Table tbl) { formatOutput("Database:", tbl.getDbName(), tableInfo); formatOutput("Owner:", tbl.getOwner(), tableInfo); formatOutput("CreateTime:", formatDate(tbl.getTTable().getCreateTime()), tableInfo); formatOutput("LastAccessTime:", formatDate(tbl.getTTable().getLastAccessTime()), tableInfo); String protectMode = tbl.getProtectMode().toString(); formatOutput("Protect Mode:", protectMode == null ? "None" : protectMode, tableInfo); formatOutput("Retention:", Integer.toString(tbl.getRetention()), tableInfo); if (!tbl.isView()) { formatOutput("Location:", tbl.getDataLocation().toString(), tableInfo); } formatOutput("Table Type:", tbl.getTableType().name(), tableInfo); if (tbl.getParameters().size() > 0) { tableInfo.append("Table Parameters:").append(LINE_DELIM); displayAllParameters(tbl.getParameters(), tableInfo); } } private static void getPartitionMetaDataInformation(StringBuilder tableInfo, Partition part) { formatOutput("Partition Value:", part.getValues().toString(), tableInfo); formatOutput("Database:", part.getTPartition().getDbName(), tableInfo); formatOutput("Table:", part.getTable().getTableName(), tableInfo); formatOutput("CreateTime:", formatDate(part.getTPartition().getCreateTime()), tableInfo); formatOutput("LastAccessTime:", formatDate(part.getTPartition().getLastAccessTime()), tableInfo); String protectMode = part.getProtectMode().toString(); formatOutput("Protect Mode:", protectMode == null ? "None" : protectMode, tableInfo); formatOutput("Location:", part.getLocation(), tableInfo); if (part.getTPartition().getParameters().size() > 0) { tableInfo.append("Partition Parameters:").append(LINE_DELIM); displayAllParameters(part.getTPartition().getParameters(), tableInfo); } } private static void displayAllParameters(Map<String, String> params, StringBuilder tableInfo) { List<String> keys = new ArrayList<String>(params.keySet()); Collections.sort(keys); for (String key : keys) { tableInfo.append(FIELD_DELIM); // Ensures all params are indented. formatOutput(key, StringEscapeUtils.escapeJava(params.get(key)), tableInfo); } } private static void formatFieldSchemas(StringBuilder tableInfo, FieldSchema col) { String comment = col.getComment() != null ? col.getComment() : "None"; formatOutput(col.getName(), col.getType(), comment, tableInfo); } private static String formatDate(long timeInSeconds) { if (timeInSeconds != 0) { Date date = new Date(timeInSeconds * 1000); return date.toString(); } return "UNKNOWN"; } private static void formatOutput(String[] fields, StringBuilder tableInfo) { for (String field : fields) { if (field == null) { tableInfo.append(FIELD_DELIM); continue; } tableInfo.append(String.format("%-" + ALIGNMENT + "s", field)).append(FIELD_DELIM); } tableInfo.append(LINE_DELIM); } private static void formatOutput(String name, String value, StringBuilder tableInfo) { tableInfo.append(String.format("%-" + ALIGNMENT + "s", name)).append(FIELD_DELIM); tableInfo.append(String.format("%-" + ALIGNMENT + "s", value)).append(LINE_DELIM); } private static void formatOutput(String col1, String col2, String col3, StringBuilder tableInfo) { tableInfo.append(String.format("%-" + ALIGNMENT + "s", col1)).append(FIELD_DELIM); tableInfo.append(String.format("%-" + ALIGNMENT + "s", col2)).append(FIELD_DELIM); tableInfo.append(String.format("%-" + ALIGNMENT + "s", col3)).append(LINE_DELIM); } public static String[] getColumnsHeader() { return DescTableDesc.getSchema().split("#")[0].split(","); } public static String getIndexColumnsHeader() { StringBuilder indexCols = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE); formatOutput(ShowIndexesDesc.getSchema().split("#")[0].split(","), indexCols); return indexCols.toString(); } }