/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.jdbc.util;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLXML;
/**
* @since 4.2
*/
@SuppressWarnings("nls")
public class ResultSetUtil {
public static final int DEFAULT_MAX_COL_WIDTH = 29;
private static final String SPACER = " "; //$NON-NLS-1$
private static final String NULL = "<null>"; //$NON-NLS-1$
private static final String MORE = "$ ";
public static void printResultSet(ResultSet rs) throws SQLException, IOException {
PrintWriter pw = new PrintWriter(System.out);
printResultSet(rs, 100, true, pw);
pw.flush();
}
/**
* Prints the ResultSet (and optionally the ResultSetMetaData) to a stream. If you're using the stream from getPrintStream(),
* then you can also compare data with expected results.
* @param rs
* @param maxColWidth the max width a column is allowed to have. The column will be wider than this value only if the column name is longer.
* @param printMetadata
* @param out
* @throws SQLException
* @throws IOException
* @since 4.2
*/
public static void printResultSet(ResultSet rs, int maxColWidth, boolean printMetadata, Writer out) throws SQLException, IOException {
if (maxColWidth < 0) {
maxColWidth = DEFAULT_MAX_COL_WIDTH;
}
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
int[] sizes = new int[count];
StringWriter types = new StringWriter();
StringWriter columns = new StringWriter();
for (int i = 1; i <= count; i++) {
String columnName = rsmd.getColumnLabel(i);
String typeName = rsmd.getColumnTypeName(i);
if (maxColWidth == 0) {
// Sets the width of the column to the wider of the column name and the column type name.
sizes[i-1] = Math.max(columnName.length(), typeName.length());
} else {
// Sets the width of the column to the wider of the column name and the column display size (which cannot exceed maxColWidth).
sizes[i-1] = Math.max(Math.max(columnName.length(), typeName.length()), // takes into account the type name width
Math.min(rsmd.getColumnDisplaySize(i), maxColWidth));
}
types.write(resizeString(typeName, sizes[i-1]));
columns.write(resizeString(columnName, sizes[i-1]));
if (i != count) {
types.write(SPACER);
columns.write(SPACER);
}
}
out.append(types.toString()).append("\n");
out.append(columns.toString()).append("\n");
int totalRows = 0;
while (rs.next()) {
for (int j = 1; j <= count; j++) {
Object obj = rs.getObject(j);
if (obj instanceof SQLXML) {
obj = ((SQLXML)obj).getString();
} else if (obj instanceof Clob) {
obj = "Clob[" + ((Clob)obj).length() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
} else if (obj instanceof Blob) {
obj = "Blob[" + ((Blob)obj).length() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
if (maxColWidth == 0) {
out.append(obj == null ? NULL : obj.toString());
if (j != count) out.append(SPACER);
} else {
String resizedString = resizeString(obj, sizes[j-1]);
out.append(resizedString);
if (j != count && resizedString.length() <= sizes[j-1]) {
out.append(SPACER);
}
}
}
out.append("\n");
totalRows++;
}
out.append("Row Count : " + totalRows).append("\n"); //$NON-NLS-1$
if (printMetadata) printResultSetMetadata(rsmd, out);
}
private static String[] METADATA_METHODS = {
"getColumnName", //$NON-NLS-1$
"getColumnType", //$NON-NLS-1$
"getCatalogName", //$NON-NLS-1$
"getColumnClassName", //$NON-NLS-1$
"getColumnLabel", //$NON-NLS-1$
"getColumnTypeName", //$NON-NLS-1$
"getSchemaName", //$NON-NLS-1$
"getTableName", //$NON-NLS-1$
"getColumnDisplaySize", //$NON-NLS-1$
"getPrecision", //$NON-NLS-1$
"getScale", //$NON-NLS-1$
"isAutoIncrement", //$NON-NLS-1$
"isCaseSensitive", //$NON-NLS-1$
"isCurrency", //$NON-NLS-1$
"isDefinitelyWritable", //$NON-NLS-1$
"isNullable", //$NON-NLS-1$
"isReadOnly", //$NON-NLS-1$
"isSearchable", //$NON-NLS-1$
"isSigned", //$NON-NLS-1$
"isWritable", //$NON-NLS-1$
};
/**
* Prints the ResultSetMetaData values for each column
* @param rsmd
* @param out
* @throws SQLException
* @throws IOException
* @since 4.2
*/
public static void printResultSetMetadata(ResultSetMetaData rsmd, Writer out) throws SQLException, IOException {
int columns = rsmd.getColumnCount();
Class RSMD = ResultSetMetaData.class;
Class[] params = {int.class};
int numMethods = METADATA_METHODS.length;
String[][] metadataStrings = new String[columns][numMethods];
// Init the widths of the columns
int[] maxColWidths = new int[numMethods];
for (int i = 0; i < numMethods; i++) {
maxColWidths[i] = METADATA_METHODS[i].length();
}
// Buffer the metadata
for (int col = 1; col <= columns; col++) {
Object [] columnParam = {new Integer(col)};
for (int i = 0; i < numMethods; i++) {
try {
Method m = RSMD.getMethod(METADATA_METHODS[i], params);
Object obj = m.invoke(rsmd, columnParam);
String stringVal = (obj == null) ? NULL : obj.toString();
metadataStrings[col - 1][i] = stringVal;
if (maxColWidths[i] < stringVal.length()) {
maxColWidths[i] = stringVal.length();
}
} catch (Throwable t) {
}
}
}
// Print the header
for (int i = 0; i < numMethods; i++) {
out.append(resizeString(METADATA_METHODS[i], maxColWidths[i]));
if (i != numMethods) {
out.append(SPACER);
}
}
out.append("\n");
// Print the metadata from the buffer
for (int col = 0; col < columns; col++) {
for (int i = 0; i < numMethods; i++) {
out.append(resizeString(metadataStrings[col][i], maxColWidths[i]));
if (i != numMethods) {
out.append(SPACER);
}
}
out.append("\n");
}
}
private static String resizeString(Object obj, int size) {
if (obj == null) {
return resizeString(NULL, size);
}
String str = obj.toString();
if (str.length() == size) {
return str;
} else if (str.length() < size) {
return pad(str, size - str.length());
} else {
return str.substring(0, size) + MORE;
}
}
private static String pad(String str, int padding) {
StringBuffer buf = new StringBuffer(str);
for (int i = 0; i < padding; i++) {
buf.append(' ');
}
return buf.toString();
}
}