package edu.washington.escience.myria.column.builder;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.almworks.sqlite4java.SQLiteException;
import com.almworks.sqlite4java.SQLiteStatement;
import com.google.common.base.Preconditions;
import edu.washington.escience.myria.Type;
import edu.washington.escience.myria.column.DoubleColumn;
import edu.washington.escience.myria.column.mutable.DoubleMutableColumn;
import edu.washington.escience.myria.proto.DataProto.ColumnMessage;
import edu.washington.escience.myria.storage.TupleBatch;
import edu.washington.escience.myria.storage.TupleUtils;
import edu.washington.escience.myria.util.MyriaUtils;
/**
* A column of Double values.
*
*/
public final class DoubleColumnBuilder extends ColumnBuilder<Double> {
/** View of the column data as doubles. */
private final DoubleBuffer data;
/**
* If the builder has built the column.
* */
private boolean built = false;
/** Constructs an empty column that can hold up to TupleBatch.BATCH_SIZE elements. */
public DoubleColumnBuilder() {
data = DoubleBuffer.allocate(TupleUtils.getBatchSize(Type.DOUBLE_TYPE));
}
/**
* copy.
*
* @param data the underlying data
* */
private DoubleColumnBuilder(final DoubleBuffer data) {
this.data = data;
}
/**
* Constructs a DoubleColumn by deserializing the given ColumnMessage.
*
* @param message a ColumnMessage containing the contents of this column.
* @param numTuples num tuples in the column message
* @return the built column
*/
public static DoubleColumn buildFromProtobuf(final ColumnMessage message, final int numTuples) {
if (message.getType().ordinal() != ColumnMessage.Type.DOUBLE_VALUE) {
throw new IllegalArgumentException(
"Trying to construct DoubleColumn from non-DOUBLE ColumnMessage");
}
if (!message.hasDoubleColumn()) {
throw new IllegalArgumentException("ColumnMessage has type DOUBLE but no DoubleColumn");
}
ByteBuffer dataBytes = message.getDoubleColumn().getData().asReadOnlyByteBuffer();
DoubleBuffer newData = DoubleBuffer.allocate(numTuples);
for (int i = 0; i < numTuples; i++) {
newData.put(dataBytes.getDouble());
}
return new DoubleColumnBuilder(newData).build();
}
@Override
public Type getType() {
return Type.DOUBLE_TYPE;
}
@Override
public DoubleColumnBuilder appendDouble(final double value) throws BufferOverflowException {
Preconditions.checkArgument(
!built, "No further changes are allowed after the builder has built the column.");
data.put(value);
return this;
}
@Deprecated
@Override
public DoubleColumnBuilder appendObject(final Object value) throws BufferOverflowException {
Preconditions.checkArgument(
!built, "No further changes are allowed after the builder has built the column.");
return appendDouble((Double) MyriaUtils.ensureObjectIsValidType(value));
}
@Override
public DoubleColumnBuilder appendFromJdbc(final ResultSet resultSet, final int jdbcIndex)
throws SQLException, BufferOverflowException {
Preconditions.checkArgument(
!built, "No further changes are allowed after the builder has built the column.");
return appendDouble(resultSet.getDouble(jdbcIndex));
}
@Override
public DoubleColumnBuilder appendFromSQLite(final SQLiteStatement statement, final int index)
throws SQLiteException, BufferOverflowException {
Preconditions.checkArgument(
!built, "No further changes are allowed after the builder has built the column.");
return appendDouble(statement.columnDouble(index));
}
@Override
public int size() {
return data.position();
}
@Override
public DoubleColumnBuilder expandAll() {
Preconditions.checkArgument(
!built, "No further changes are allowed after the builder has built the column.");
data.position(data.capacity());
return this;
}
@Override
public DoubleColumnBuilder expand(final int size) throws BufferOverflowException {
Preconditions.checkArgument(
!built, "No further changes are allowed after the builder has built the column.");
Preconditions.checkArgument(size >= 0);
data.position(data.position() + size);
return this;
}
@Override
public DoubleColumn build() {
built = true;
return new DoubleColumn(data.array(), data.position());
}
@Override
public DoubleMutableColumn buildMutable() {
built = true;
return new DoubleMutableColumn(data.array(), data.position());
}
@Override
public void replaceDouble(final double value, final int row) throws IndexOutOfBoundsException {
Preconditions.checkArgument(
!built, "No further changes are allowed after the builder has built the column.");
Preconditions.checkElementIndex(row, data.position());
data.put(row, value);
}
@Override
@Deprecated
public Double getObject(final int row) {
return data.get(row);
}
@Override
public double getDouble(final int row) {
return data.get(row);
}
@Override
public DoubleColumnBuilder forkNewBuilder() {
double[] arr = new double[data.array().length];
System.arraycopy(data.array(), 0, arr, 0, data.position());
return new DoubleColumnBuilder(
(DoubleBuffer) DoubleBuffer.wrap(arr).position(data.position()).limit(data.limit()));
}
}