package edu.brown.benchmark.tpce.util;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import org.apache.log4j.Logger;
import org.voltdb.SQLStmt;
import org.voltdb.VoltProcedure;
import org.voltdb.VoltTable;
import org.voltdb.VoltTable.ColumnInfo;
import org.voltdb.VoltTableRow;
import org.voltdb.VoltType;
public abstract class ProcedureUtil {
private static final Logger LOG = Logger.getLogger(ProcedureUtil.class.getName());
private static final ColumnInfo[] statusColumns = { new ColumnInfo("status", VoltType.BIGINT), };
public static VoltTable getStatusTable(boolean success) {
VoltTable vt = new VoltTable(statusColumns);
vt.addRow((success ? 1 : 0));
return (vt);
}
/**
* Combine multiple VoltTables into a single table
*
* @param vts
* @return
*/
public static VoltTable combineTables(final VoltTable... vts) {
assert (vts.length > 0);
ColumnInfo cols[] = new ColumnInfo[vts[0].getColumnCount()];
for (int i = 0; i < cols.length; i++) {
cols[i] = new ColumnInfo(vts[0].getColumnName(i), vts[0].getColumnType(i));
} // FOR
VoltTable ret = new VoltTable(cols);
for (VoltTable vt : vts) {
assert (vt.getColumnCount() == ret.getColumnCount());
vt.resetRowPosition();
while (vt.advanceRow()) {
ret.add(vt.cloneRow());
} // WHILE
} // FOR
return (ret);
}
/**
* Store
*
* @param map
* @param vt
*/
public static void storeTableInMap(final Map<String, Object[]> map, final VoltTable vt) {
assert (vt != null);
assert (map != null);
int num_rows = vt.getRowCount();
while (vt.advanceRow()) {
int row_idx = vt.getActiveRowIndex();
for (int i = 0, cnt = vt.getColumnCount(); i < cnt; i++) {
String col_name = vt.getColumnName(i);
VoltType vtype = vt.getColumnType(i);
if (row_idx == 0) {
map.put(col_name, new Object[num_rows]);
}
map.get(col_name)[row_idx] = vt.get(col_name, vtype);
} // FOR
} // WHILE
}
/**
* Execute stmt with args, and put result, which is an array of columns,
* into map
*
* @param map
* the container of results of executing stmt
* @param sp
* the store procedure that executes stmt
* @param stmt
* the SQLStmt to be executed
* @param args
* the argument needed by stmt
* @param keys
* the names of columns in map
* @param value_refs
* the references of values matching the keys. Each reference is
* one of {column_index, column_name, key_name}
* @return the size of the first VoltTable among the array of VoltTable
* returned by executing stmt
*/
public static int execute(Map<String, Object[]> map, VoltProcedure sp, SQLStmt stmt, Object[] args, String[] keys, Object[] value_refs) {
LOG.info("Executing SQL: " + stmt);
System.out.println("ProcedureUtil line 97: " + args.length);
String debug = "PARAMS:";
for (Object arg : args) {
debug += " " + arg;
}
LOG.info(debug);
sp.voltQueueSQL(stmt, args);
VoltTable table = sp.voltExecuteSQL()[0];
System.out.println(table);
if (keys == null) {
assert (value_refs == null);
return -1;
}
assert (keys.length == value_refs.length);
int row_count = table.getRowCount();
System.out.println("ProcedureUtil line 116: " + row_count);
// each key corresponds to a column of length row_count
for (String key : keys)
map.put(key, new Object[row_count]);
// for update, delete, insert, keys is empty
if (keys.length > 0) {
for (int i = 0; i < row_count; i++) {
VoltTableRow row = table.fetchRow(i);
for (int j = 0; j < keys.length; j++) {
Object[] vals = map.get(keys[j]);
Object ref = value_refs[j];
if (ref instanceof Integer) {
// ref is column_index
vals[i] = row.get(j, table.getColumnType(j));
} else {
assert (ref instanceof String);
int idx = table.getColumnIndex((String) ref);
if (idx >= 0) {
// ref is column_name
vals[i] = row.get(idx, table.getColumnType(idx));
} else {
// ref is key_name
if (map.get(ref).length == 1) {
vals[i] = map.get(ref)[0];
} else {
vals[i] = map.get(ref)[i];
}
}
}
}
}
}
return row_count;
}
/**
* Execute stmt with args
*
* @param sp
* @param stmt
* @param args
*/
public static void execute(VoltProcedure sp, SQLStmt stmt, Object[] args) {
execute(null, sp, stmt, args, null, null);
}
/**
* @param map
* @return
*/
public static VoltTable[] mapToTable(Map<String, Object[]> map) {
VoltTable[] tables = new VoltTable[map.size()];
int i = 0;
Collection<String> keys = map.keySet();
for (String key : keys) {
Object[] vals = map.get(key);
VoltTable table = new VoltTable(new VoltTable.ColumnInfo(key, ProcedureUtil.getVoltType(vals[0])));
for (Object v : vals) {
table.addRow(v);
}
tables[i++] = table;
}
return tables;
}
public static VoltType getVoltType(Object obj) {
if (obj instanceof Byte)
return VoltType.TINYINT;
if (obj instanceof Short)
return VoltType.SMALLINT;
if (obj instanceof Integer)
return VoltType.INTEGER;
if (obj instanceof Long)
return VoltType.BIGINT;
if (obj instanceof Double || obj instanceof Float)
return VoltType.FLOAT;
if (obj instanceof Date)
return VoltType.TIMESTAMP;
if (obj instanceof String || obj instanceof Byte[])
return VoltType.STRING;
if (obj instanceof BigDecimal)
return VoltType.DECIMAL;
throw new RuntimeException("The type of " + obj + " is not supported");
}
}