blob: ba4f6a76472d27adb877caa7b8b7f3d1aad9ff0f [file] [log] [blame]
/**
* 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 org.apache.commons.lang.StringEscapeUtils;
import org.apache.hadoop.hive.common.type.HiveDecimal;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hadoop.hive.metastore.TableType;
import org.apache.hadoop.hive.metastore.api.BinaryColumnStatsData;
import org.apache.hadoop.hive.metastore.api.BooleanColumnStatsData;
import org.apache.hadoop.hive.metastore.api.ColumnStatisticsData;
import org.apache.hadoop.hive.metastore.api.ColumnStatisticsObj;
import org.apache.hadoop.hive.metastore.api.DateColumnStatsData;
import org.apache.hadoop.hive.metastore.api.Decimal;
import org.apache.hadoop.hive.metastore.api.DecimalColumnStatsData;
import org.apache.hadoop.hive.metastore.api.DoubleColumnStatsData;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.Index;
import org.apache.hadoop.hive.metastore.api.LongColumnStatsData;
import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
import org.apache.hadoop.hive.metastore.api.StringColumnStatsData;
import org.apache.hadoop.hive.ql.index.HiveIndex;
import org.apache.hadoop.hive.ql.index.HiveIndex.IndexType;
import org.apache.hadoop.hive.ql.metadata.ForeignKeyInfo;
import org.apache.hadoop.hive.ql.metadata.Partition;
import org.apache.hadoop.hive.ql.metadata.PrimaryKeyInfo;
import org.apache.hadoop.hive.ql.metadata.Table;
import org.apache.hadoop.hive.ql.metadata.ForeignKeyInfo.ForeignKeyCol;
import org.apache.hadoop.hive.ql.plan.DescTableDesc;
import org.apache.hadoop.hive.ql.plan.PlanUtils;
import org.apache.hadoop.hive.ql.plan.ShowIndexesDesc;
import org.apache.hadoop.hive.serde2.io.DateWritable;
import org.apache.hive.common.util.HiveStringUtils;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
/**
* 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";
static final int DEFAULT_STRINGBUILDER_SIZE = 2048;
private static final int ALIGNMENT = 20;
private MetaDataFormatUtils() {
}
private static void formatColumnsHeader(StringBuilder columnInformation,
List<ColumnStatisticsObj> colStats) {
columnInformation.append("# "); // Easy for shell scripts to ignore
formatOutput(getColumnsHeader(colStats), columnInformation);
columnInformation.append(LINE_DELIM);
}
/**
* Write formatted information about the given columns to a string
* @param cols - list of columns
* @param printHeader - if header should be included
* @param isOutputPadded - make it more human readable by setting indentation
* with spaces. Turned off for use by HiveServer2
* @param colStats
* @return string with formatted column information
*/
public static String getAllColumnsInformation(List<FieldSchema> cols,
boolean printHeader, boolean isOutputPadded, List<ColumnStatisticsObj> colStats) {
StringBuilder columnInformation = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE);
if(printHeader){
formatColumnsHeader(columnInformation, colStats);
}
formatAllFields(columnInformation, cols, isOutputPadded, colStats);
return columnInformation.toString();
}
/**
* Write formatted information about the given columns, including partition
* columns to a string
* @param cols - list of columns
* @param partCols - list of partition columns
* @param printHeader - if header should be included
* @param isOutputPadded - make it more human readable by setting indentation
* with spaces. Turned off for use by HiveServer2
* @param showParColsSep - show partition column separator
* @return string with formatted column information
*/
public static String getAllColumnsInformation(List<FieldSchema> cols,
List<FieldSchema> partCols, boolean printHeader, boolean isOutputPadded, boolean showPartColsSep) {
StringBuilder columnInformation = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE);
if(printHeader){
formatColumnsHeader(columnInformation, null);
}
formatAllFields(columnInformation, cols, isOutputPadded, null);
if ((partCols != null) && !partCols.isEmpty() && showPartColsSep) {
columnInformation.append(LINE_DELIM).append("# Partition Information")
.append(LINE_DELIM);
formatColumnsHeader(columnInformation, null);
formatAllFields(columnInformation, partCols, isOutputPadded, null);
}
return columnInformation.toString();
}
/**
* Write formatted column information into given StringBuilder
* @param tableInfo - StringBuilder to append column information into
* @param cols - list of columns
* @param isOutputPadded - make it more human readable by setting indentation
* with spaces. Turned off for use by HiveServer2
* @param colStats
*/
private static void formatAllFields(StringBuilder tableInfo,
List<FieldSchema> cols, boolean isOutputPadded, List<ColumnStatisticsObj> colStats) {
for (FieldSchema col : cols) {
if(isOutputPadded) {
formatWithIndentation(col.getName(), col.getType(), getComment(col), tableInfo, colStats);
}
else {
formatWithoutIndentation(col.getName(), col.getType(), col.getComment(), tableInfo, colStats);
}
}
}
private static String convertToString(Decimal val) {
if (val == null) {
return "";
}
HiveDecimal result = HiveDecimal.create(new BigInteger(val.getUnscaled()), val.getScale());
if (result != null) {
return result.toString();
} else {
return "";
}
}
private static String convertToString(org.apache.hadoop.hive.metastore.api.Date val) {
if (val == null) {
return "";
}
DateWritable writableValue = new DateWritable((int) val.getDaysSinceEpoch());
return writableValue.toString();
}
private static ColumnStatisticsObj getColumnStatisticsObject(String colName,
String colType, List<ColumnStatisticsObj> colStats) {
if (colStats != null && !colStats.isEmpty()) {
for (ColumnStatisticsObj cso : colStats) {
if (cso.getColName().equalsIgnoreCase(colName)
&& cso.getColType().equalsIgnoreCase(colType)) {
return cso;
}
}
}
return null;
}
private static void formatWithoutIndentation(String name, String type, String comment,
StringBuilder colBuffer, List<ColumnStatisticsObj> colStats) {
colBuffer.append(name);
colBuffer.append(FIELD_DELIM);
colBuffer.append(type);
colBuffer.append(FIELD_DELIM);
if (colStats != null) {
ColumnStatisticsObj cso = getColumnStatisticsObject(name, type, colStats);
if (cso != null) {
ColumnStatisticsData csd = cso.getStatsData();
if (csd.isSetBinaryStats()) {
BinaryColumnStatsData bcsd = csd.getBinaryStats();
appendColumnStatsNoFormatting(colBuffer, "", "", bcsd.getNumNulls(), "",
bcsd.getAvgColLen(), bcsd.getMaxColLen(), "", "");
} else if (csd.isSetStringStats()) {
StringColumnStatsData scsd = csd.getStringStats();
appendColumnStatsNoFormatting(colBuffer, "", "", scsd.getNumNulls(), scsd.getNumDVs(),
scsd.getAvgColLen(), scsd.getMaxColLen(), "", "");
} else if (csd.isSetBooleanStats()) {
BooleanColumnStatsData bcsd = csd.getBooleanStats();
appendColumnStatsNoFormatting(colBuffer, "", "", bcsd.getNumNulls(), "", "", "",
bcsd.getNumTrues(), bcsd.getNumFalses());
} else if (csd.isSetDecimalStats()) {
DecimalColumnStatsData dcsd = csd.getDecimalStats();
appendColumnStatsNoFormatting(colBuffer, convertToString(dcsd.getLowValue()),
convertToString(dcsd.getHighValue()), dcsd.getNumNulls(), dcsd.getNumDVs(),
"", "", "", "");
} else if (csd.isSetDoubleStats()) {
DoubleColumnStatsData dcsd = csd.getDoubleStats();
appendColumnStatsNoFormatting(colBuffer, dcsd.getLowValue(), dcsd.getHighValue(),
dcsd.getNumNulls(), dcsd.getNumDVs(), "", "", "", "");
} else if (csd.isSetLongStats()) {
LongColumnStatsData lcsd = csd.getLongStats();
appendColumnStatsNoFormatting(colBuffer, lcsd.getLowValue(), lcsd.getHighValue(),
lcsd.getNumNulls(), lcsd.getNumDVs(), "", "", "", "");
} else if (csd.isSetDateStats()) {
DateColumnStatsData dcsd = csd.getDateStats();
appendColumnStatsNoFormatting(colBuffer,
convertToString(dcsd.getLowValue()),
convertToString(dcsd.getHighValue()),
dcsd.getNumNulls(), dcsd.getNumDVs(), "", "", "", "");
}
} else {
appendColumnStatsNoFormatting(colBuffer, "", "", "", "", "", "", "", "");
}
}
colBuffer.append(comment == null ? "" : comment);
colBuffer.append(LINE_DELIM);
}
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();
}
public static String getConstraintsInformation(PrimaryKeyInfo pkInfo, ForeignKeyInfo fkInfo) {
StringBuilder constraintsInfo = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE);
constraintsInfo.append(LINE_DELIM).append("# Constraints").append(LINE_DELIM);
if (pkInfo != null && !pkInfo.getColNames().isEmpty()) {
constraintsInfo.append(LINE_DELIM).append("# Primary Key").append(LINE_DELIM);
getPrimaryKeyInformation(constraintsInfo, pkInfo);
}
if (fkInfo != null && !fkInfo.getForeignKeys().isEmpty()) {
constraintsInfo.append(LINE_DELIM).append("# Foreign Keys").append(LINE_DELIM);
getForeignKeysInformation(constraintsInfo, fkInfo);
}
return constraintsInfo.toString();
}
private static void getPrimaryKeyInformation(StringBuilder constraintsInfo,
PrimaryKeyInfo pkInfo) {
formatOutput("Table:", pkInfo.getDatabaseName()+"."+pkInfo.getTableName(), constraintsInfo);
formatOutput("Constraint Name:", pkInfo.getConstraintName(), constraintsInfo);
Map<Integer, String> colNames = pkInfo.getColNames();
final String columnNames = "Column Names:";
constraintsInfo.append(String.format("%-" + ALIGNMENT + "s", columnNames)).append(FIELD_DELIM);
if (colNames != null && colNames.size() > 0) {
formatOutput(colNames.values().toArray(new String[colNames.size()]), constraintsInfo);
}
}
private static void getForeignKeyColInformation(StringBuilder constraintsInfo,
ForeignKeyCol fkCol) {
String[] fkcFields = new String[3];
fkcFields[0] = "Parent Column Name:" + fkCol.parentDatabaseName +
"."+ fkCol.parentTableName + "." + fkCol.parentColName;
fkcFields[1] = "Column Name:" + fkCol.childColName;
fkcFields[2] = "Key Sequence:" + fkCol.position;
formatOutput(fkcFields, constraintsInfo);
}
private static void getForeignKeyRelInformation(
StringBuilder constraintsInfo,
String constraintName,
List<ForeignKeyCol> fkRel) {
formatOutput("Constraint Name:", constraintName, constraintsInfo);
if (fkRel != null && fkRel.size() > 0) {
for (ForeignKeyCol fkc : fkRel) {
getForeignKeyColInformation(constraintsInfo, fkc);
}
}
constraintsInfo.append(LINE_DELIM);
}
private static void getForeignKeysInformation(StringBuilder constraintsInfo,
ForeignKeyInfo fkInfo) {
formatOutput("Table:",
fkInfo.getChildDatabaseName()+"."+fkInfo.getChildTableName(),
constraintsInfo);
Map<String, List<ForeignKeyCol>> foreignKeys = fkInfo.getForeignKeys();
if (foreignKeys != null && foreignKeys.size() > 0) {
for (Map.Entry<String, List<ForeignKeyCol>> me : foreignKeys.entrySet()) {
getForeignKeyRelInformation(constraintsInfo, me.getKey(), me.getValue());
}
}
}
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.isStoredAsSubDirectories()) {// optional parameter
formatOutput("Stored As SubDirectories:", "Yes", tableInfo);
}
if (null != storageDesc.getSkewedInfo()) {
List<String> skewedColNames = sortedList(storageDesc.getSkewedInfo().getSkewedColNames());
if ((skewedColNames != null) && (skewedColNames.size() > 0)) {
formatOutput("Skewed Columns:", skewedColNames.toString(), tableInfo);
}
List<List<String>> skewedColValues = sortedList(
storageDesc.getSkewedInfo().getSkewedColValues(), new VectorComparator<String>());
if ((skewedColValues != null) && (skewedColValues.size() > 0)) {
formatOutput("Skewed Values:", skewedColValues.toString(), tableInfo);
}
Map<List<String>, String> skewedColMap = new TreeMap<>(new VectorComparator<String>());
skewedColMap.putAll(storageDesc.getSkewedInfo().getSkewedColValueLocationMaps());
if ((skewedColMap!=null) && (skewedColMap.size() > 0)) {
formatOutput("Skewed Value to Path:", skewedColMap.toString(),
tableInfo);
Map<List<String>, String> truncatedSkewedColMap = new TreeMap<List<String>, String>(new VectorComparator<String>());
// walk through existing map to truncate path so that test won't mask it
// then we can verify location is right
Set<Entry<List<String>, String>> entries = skewedColMap.entrySet();
for (Entry<List<String>, String> entry : entries) {
truncatedSkewedColMap.put(entry.getKey(),
PlanUtils.removePrefixFromWarehouseConfig(entry.getValue()));
}
formatOutput("Skewed Value to Truncated Path:",
truncatedSkewedColMap.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);
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, false);
}
}
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);
formatOutput("Location:", part.getLocation(), tableInfo);
if (part.getTPartition().getParameters().size() > 0) {
tableInfo.append("Partition Parameters:").append(LINE_DELIM);
displayAllParameters(part.getTPartition().getParameters(), tableInfo);
}
}
/**
* Display key, value pairs of the parameters. The characters will be escaped
* including unicode.
*/
private static void displayAllParameters(Map<String, String> params, StringBuilder tableInfo) {
displayAllParameters(params, tableInfo, true);
}
/**
* Display key, value pairs of the parameters. The characters will be escaped
* including unicode if escapeUnicode is true; otherwise the characters other
* than unicode will be escaped.
*/
private static void displayAllParameters(Map<String, String> params, StringBuilder tableInfo, boolean escapeUnicode) {
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,
escapeUnicode ? StringEscapeUtils.escapeJava(params.get(key)) : HiveStringUtils.escapeJava(params.get(key)),
tableInfo);
}
}
static String getComment(FieldSchema col) {
return col.getComment() != null ? col.getComment() : "";
}
/**
* Compares to lists of object T as vectors
*
* @param <T> the base object type. Must be {@link Comparable}
*/
private static class VectorComparator<T extends Comparable<T>> implements Comparator<List<T>>{
@Override
public int compare(List<T> listA, List<T> listB) {
for (int i = 0; i < listA.size() && i < listB.size(); i++) {
T valA = listA.get(i);
T valB = listB.get(i);
if (valA != null) {
int ret = valA.compareTo(valB);
if (ret != 0) {
return ret;
}
} else {
if (valB != null) {
return -1;
}
}
}
return Integer.compare(listA.size(), listB.size());
}
}
/**
* Returns a sorted version of the given list
*/
static <T extends Comparable<T>> List<T> sortedList(List<T> list){
if (list == null || list.size() <= 1) {
return list;
}
ArrayList<T> ret = new ArrayList<>();
ret.addAll(list);
Collections.sort(ret);
return ret;
}
/**
* Returns a sorted version of the given list, using the provided comparator
*/
static <T> List<T> sortedList(List<T> list, Comparator<T> comp) {
if (list == null || list.size() <= 1) {
return list;
}
ArrayList<T> ret = new ArrayList<>();
ret.addAll(list);
Collections.sort(ret,comp);
return ret;
}
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 formatWithIndentation(String colName, String colType, String colComment,
StringBuilder tableInfo, List<ColumnStatisticsObj> colStats) {
tableInfo.append(String.format("%-" + ALIGNMENT + "s", colName)).append(FIELD_DELIM);
tableInfo.append(String.format("%-" + ALIGNMENT + "s", colType)).append(FIELD_DELIM);
if (colStats != null) {
ColumnStatisticsObj cso = getColumnStatisticsObject(colName, colType, colStats);
if (cso != null) {
ColumnStatisticsData csd = cso.getStatsData();
if (csd.isSetBinaryStats()) {
BinaryColumnStatsData bcsd = csd.getBinaryStats();
appendColumnStats(tableInfo, "", "", bcsd.getNumNulls(), "", bcsd.getAvgColLen(),
bcsd.getMaxColLen(), "", "");
} else if (csd.isSetStringStats()) {
StringColumnStatsData scsd = csd.getStringStats();
appendColumnStats(tableInfo, "", "", scsd.getNumNulls(), scsd.getNumDVs(),
scsd.getAvgColLen(), scsd.getMaxColLen(), "", "");
} else if (csd.isSetBooleanStats()) {
BooleanColumnStatsData bcsd = csd.getBooleanStats();
appendColumnStats(tableInfo, "", "", bcsd.getNumNulls(), "", "", "",
bcsd.getNumTrues(), bcsd.getNumFalses());
} else if (csd.isSetDecimalStats()) {
DecimalColumnStatsData dcsd = csd.getDecimalStats();
appendColumnStats(tableInfo, convertToString(dcsd.getLowValue()),
convertToString(dcsd.getHighValue()), dcsd.getNumNulls(), dcsd.getNumDVs(),
"", "", "", "");
} else if (csd.isSetDoubleStats()) {
DoubleColumnStatsData dcsd = csd.getDoubleStats();
appendColumnStats(tableInfo, dcsd.getLowValue(), dcsd.getHighValue(), dcsd.getNumNulls(),
dcsd.getNumDVs(), "", "", "", "");
} else if (csd.isSetLongStats()) {
LongColumnStatsData lcsd = csd.getLongStats();
appendColumnStats(tableInfo, lcsd.getLowValue(), lcsd.getHighValue(), lcsd.getNumNulls(),
lcsd.getNumDVs(), "", "", "", "");
} else if (csd.isSetDateStats()) {
DateColumnStatsData dcsd = csd.getDateStats();
appendColumnStats(tableInfo,
convertToString(dcsd.getLowValue()),
convertToString(dcsd.getHighValue()),
dcsd.getNumNulls(), dcsd.getNumDVs(), "", "", "", "");
}
} else {
appendColumnStats(tableInfo, "", "", "", "", "", "", "", "");
}
}
// comment indent processing for multi-line comments
// comments should be indented the same amount on each line
// if the first line comment starts indented by k,
// the following line comments should also be indented by k
String[] commentSegments = colComment.split("\n|\r|\r\n");
tableInfo.append(String.format("%-" + ALIGNMENT + "s", commentSegments[0])).append(LINE_DELIM);
int colNameLength = ALIGNMENT > colName.length() ? ALIGNMENT : colName.length();
int colTypeLength = ALIGNMENT > colType.length() ? ALIGNMENT : colType.length();
for (int i = 1; i < commentSegments.length; i++) {
tableInfo.append(String.format("%" + colNameLength + "s" + FIELD_DELIM + "%"
+ colTypeLength + "s" + FIELD_DELIM + "%s", "", "", commentSegments[i])).append(LINE_DELIM);
}
}
private static void appendColumnStats(StringBuilder sb, Object min, Object max, Object numNulls,
Object ndv, Object avgColLen, Object maxColLen, Object numTrues, Object numFalses) {
sb.append(String.format("%-" + ALIGNMENT + "s", min)).append(FIELD_DELIM);
sb.append(String.format("%-" + ALIGNMENT + "s", max)).append(FIELD_DELIM);
sb.append(String.format("%-" + ALIGNMENT + "s", numNulls)).append(FIELD_DELIM);
sb.append(String.format("%-" + ALIGNMENT + "s", ndv)).append(FIELD_DELIM);
sb.append(String.format("%-" + ALIGNMENT + "s", avgColLen)).append(FIELD_DELIM);
sb.append(String.format("%-" + ALIGNMENT + "s", maxColLen)).append(FIELD_DELIM);
sb.append(String.format("%-" + ALIGNMENT + "s", numTrues)).append(FIELD_DELIM);
sb.append(String.format("%-" + ALIGNMENT + "s", numFalses)).append(FIELD_DELIM);
}
private static void appendColumnStatsNoFormatting(StringBuilder sb, Object min,
Object max, Object numNulls, Object ndv, Object avgColLen, Object maxColLen,
Object numTrues, Object numFalses) {
sb.append(min).append(FIELD_DELIM);
sb.append(max).append(FIELD_DELIM);
sb.append(numNulls).append(FIELD_DELIM);
sb.append(ndv).append(FIELD_DELIM);
sb.append(avgColLen).append(FIELD_DELIM);
sb.append(maxColLen).append(FIELD_DELIM);
sb.append(numTrues).append(FIELD_DELIM);
sb.append(numFalses).append(FIELD_DELIM);
}
public static String[] getColumnsHeader(List<ColumnStatisticsObj> colStats) {
boolean showColStats = false;
if (colStats != null) {
showColStats = true;
}
return DescTableDesc.getSchema(showColStats).split("#")[0].split(",");
}
public static String getIndexColumnsHeader() {
StringBuilder indexCols = new StringBuilder(DEFAULT_STRINGBUILDER_SIZE);
formatOutput(ShowIndexesDesc.getSchema().split("#")[0].split(","), indexCols);
return indexCols.toString();
}
public static MetaDataFormatter getFormatter(HiveConf conf) {
if ("json".equals(conf.get(HiveConf.ConfVars.HIVE_DDL_OUTPUT_FORMAT.varname, "text"))) {
return new JsonMetaDataFormatter();
} else {
return new TextMetaDataFormatter(conf.getIntVar(HiveConf.ConfVars.CLIPRETTYOUTPUTNUMCOLS), conf.getBoolVar(ConfVars.HIVE_DISPLAY_PARTITION_COLUMNS_SEPARATELY));
}
}
}