package org.voltdb.utils;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collection;
import org.voltdb.VoltTable;
import org.voltdb.VoltType;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Table;
import org.voltdb.types.SortDirectionType;
import au.com.bytecode.opencsv.CSVWriter;
import edu.brown.utils.StringBoxUtil;
import edu.brown.utils.StringUtil;
import edu.brown.utils.TableUtil;
public abstract class VoltTableUtil {
public static VoltTable.ColumnInfo[] extractColumnInfo(VoltTable vt) {
VoltTable.ColumnInfo cols[] = new VoltTable.ColumnInfo[vt.getColumnCount()];
for (int i = 0; i < cols.length; i++) {
cols[i] = new VoltTable.ColumnInfo(vt.getColumnName(i), vt.getColumnType(i));
} // FOR
return (cols);
}
/**
* Dump out a VoltTable as a CSV to the given writer
* If the header flag is set to true, then the output will include
* the column names in the first row
* @param out
* @param vt
* @param write_header
*/
public static void csv(Writer out, VoltTable vt, boolean header) {
CSVWriter writer = new CSVWriter(out);
if (header) {
String cols[] = new String[vt.getColumnCount()];
for (int i = 0; i < cols.length; i++) {
cols[i] = vt.getColumnName(i);
} // FOR
writer.writeNext(cols);
}
vt.resetRowPosition();
while (vt.advanceRow()) {
String row[] = vt.getRowStringArray();
assert(row != null);
assert(row.length == vt.getColumnCount());
writer.writeNext(row);
} // WHILE
}
/**
* Pretty-printer for an array of VoltTables. This will reset
* each VoltTable's row position both before and after generating the
* formatted output
* @param results
* @return
*/
public static String format(VoltTable...results) {
StringBuilder sb = new StringBuilder();
final int num_results = results.length;
TableUtil.Format f = TableUtil.defaultTableFormat();
f.spacing_col = true;
f.trim_all = true;
f.delimiter_all = " | ";
// TABLE RESULTS
for (int result_idx = 0; result_idx < num_results; result_idx++) {
if (result_idx > 0) sb.append("\n\n");
VoltTable vt = results[result_idx];
vt.resetRowPosition();
String header[] = new String[vt.getColumnCount()];
for (int i = 0; i < header.length; i++) {
String colName = vt.getColumnName(i);
header[i] = (colName.isEmpty() ? "<empty>" : colName);
} // FOR
Object rows[][] = new Object[vt.getRowCount()][];
f.delimiter_rows = new String[rows.length];
for (int i = 0; i < rows.length; i++) {
rows[i] = new Object[header.length];
f.delimiter_rows[i] = "-";
boolean adv = vt.advanceRow();
assert(adv);
for (int j = 0; j < header.length; j++) {
rows[i][j] = vt.get(j);
if (vt.wasNull()) {
rows[i][j] = null;
}
} // FOR (cols)
} // FOR (rows)
sb.append(String.format("Result #%d / %d\n", result_idx+1, num_results));
String resultTable = TableUtil.table(f, header, rows);
resultTable = StringBoxUtil.box(resultTable,
StringBoxUtil.UNICODE_BOX_HORIZONTAL,
StringBoxUtil.UNICODE_BOX_VERTICAL,
null,
StringBoxUtil.UNICODE_BOX_CORNERS);
sb.append(StringUtil.prefix(resultTable, " "));
vt.resetRowPosition();
} // FOR
return (sb.toString());
}
/**
* Sort a VoltTable based on a series of columns and directions.
* Note that this utility method is not a sort in place and thus it
* will create a second copy of the table's data.
* @param table
* @param cols
* @return
*/
@SuppressWarnings("unchecked")
public static VoltTable sort(VoltTable table, Pair<Integer, SortDirectionType>...cols) {
if (cols.length == 0) return (table);
Object rows[][] = new Object[table.getRowCount()][];
table.resetRowPosition();
int row_idx = -1;
while (table.advanceRow()) {
rows[++row_idx] = table.getRowArray();
assert(rows[row_idx] != null) : "Null row at " + row_idx;
} // FOR
VoltTableComparator comparator = new VoltTableComparator(table, cols);
Arrays.sort(rows, comparator);
VoltTable clone = new VoltTable(table);
for (int i = 0; i < rows.length; i++) {
clone.addRow(rows[i]);
} // FOR
return (clone);
}
/**
* Combine multiple VoltTables into a single object
* This assumes that all of the tables have the same schema
* @param tables
* @return
*/
public static VoltTable union(Collection<VoltTable> tables) {
VoltTable result = null;
if (tables != null) {
for (VoltTable vt : tables) {
if (vt == null) continue;
if (result == null) {
result = new VoltTable(vt);
}
vt.resetRowPosition();
while (vt.advanceRow()) {
result.add(vt);
} // WHILE
} // FOR
}
return (result);
}
/**
* Returns a row with random data that can be added to this VoltTable
* @param table
* @return
*/
public static Object[] getRandomRow(VoltTable volt_tbl) {
Object row[] = new Object[volt_tbl.getColumnCount()];
for (int i = 0; i < row.length; i++) {
VoltType vtype = volt_tbl.getColumnType(i);
row[i] = VoltTypeUtil.getRandomValue(vtype);
// HACK: We don't actually now the VARCHAR length here,
// so we'll just leave it at 8
if (vtype == VoltType.STRING) {
row[i] = StringUtil.abbrv(row[i].toString(), 8, false);
}
} // FOR
return (row);
}
/**
* Returns a row with random data that can be added to this VoltTable
* @param table
* @return
*/
public static Object[] getRandomRow(Table catalog_tbl) {
Object row[] = new Object[catalog_tbl.getColumns().size()];
for (Column catalog_col : catalog_tbl.getColumns()) {
int i = catalog_col.getIndex();
VoltType vtype = VoltType.get(catalog_col.getType());
row[i] = VoltTypeUtil.getRandomValue(vtype);
if (vtype == VoltType.STRING) {
row[i] = StringUtil.abbrv(row[i].toString(), catalog_col.getSize(), false);
}
} // FOR
return (row);
}
}