package cassandra.cql;
import cassandra.CassandraSession;
import cassandra.cql.type.CQL3Type;
import cassandra.metadata.ColumnMetadata;
import cassandra.metadata.Partitioner;
import cassandra.metadata.TableMetadata;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.*;
public class PreparedStatement extends AbstractStatement<PreparedStatement> {
public static class StatementId {
private final byte[] array;
public StatementId(byte[] array) {
this.array = array;
}
public byte[] array() {
return array;
}
public int size() {
return array.length;
}
@Override
public int hashCode() {
return Arrays.hashCode(array);
}
@Override
public boolean equals(Object o) {
return this == o || o != null && o instanceof StatementId && Arrays.equals(array(), ((StatementId)o).array());
}
@Override
public String toString() {
return Partitioner.Hex.bytesToHex(array);
}
}
private final StatementId id;
private final RowMetadata metadata, parameterMetadata;
private final int[] partitionKeyIndexes;
public PreparedStatement(CassandraSession session, StatementId id, String query, RowMetadata metadata, RowMetadata parameterMetadata) {
this.id = id;
this.metadata = metadata;
this.parameterMetadata = parameterMetadata;
setSession(session);
setQuery(query);
int[] idxs = null;
if (parameterMetadata != null && parameterMetadata.getColumnCount() > 0) {
String keyspaceName = parameterMetadata.getKeyspaceName(0);
String tableName = parameterMetadata.getTableName(0);
setKeyspace(keyspaceName);
setParameters(new ByteBuffer[parameterMetadata.getColumnCount()]);
TableMetadata table = session.metadata().getTable(keyspaceName, tableName);
if (table != null) {
List<ColumnMetadata> pkList = table.getPartitionKey();
idxs = new int[pkList.size()];
for (int i = 0; i < idxs.length; i++) {
idxs[i] = -1;
}
for (int i = 0; i < parameterMetadata.getColumnCount(); i++) {
String name = parameterMetadata.getColumnName(i);
for (int j = 0; j < pkList.size(); j++) {
if (name.equals(pkList.get(j).getName())) {
idxs[j] = i;
break;
}
}
}
boolean hasnull = false;
for (int indexe : idxs) {
if (indexe < 0) {
hasnull = true;
break;
}
}
if (hasnull) {
idxs = null;
}
}
}
partitionKeyIndexes = idxs;
}
private PreparedStatement(PreparedStatement pstmt) {
super(pstmt);
this.id = pstmt.getId();
this.metadata = pstmt.getMetadata();
this.parameterMetadata = pstmt.getParameterMetadata();
partitionKeyIndexes = pstmt.partitionKeyIndexes;
}
public StatementId getId() {
return id;
}
public RowMetadata getMetadata() {
return metadata;
}
public RowMetadata getParameterMetadata() {
return parameterMetadata;
}
public PreparedStatement setBool(int column, boolean value) {
return setValue(column, CQL3Type.Name.BOOLEAN, value);
}
public PreparedStatement setBool(String column, boolean value) {
return setValue(column, CQL3Type.Name.BOOLEAN, value);
}
public PreparedStatement setBlob(int column, ByteBuffer value) {
return setValue(column, CQL3Type.Name.BLOB, value);
}
public PreparedStatement setBlob(String column, ByteBuffer value) {
return setValue(column, CQL3Type.Name.BLOB, value);
}
public PreparedStatement setDate(int column, Date value) {
return setValue(column, CQL3Type.Name.TIMESTAMP, value);
}
public PreparedStatement setDate(String column, Date value) {
return setValue(column, CQL3Type.Name.TIMESTAMP, value);
}
public PreparedStatement setDecimal(int column, BigDecimal value) {
return setValue(column, CQL3Type.Name.DECIMAL, value);
}
public PreparedStatement setDecimal(String column, BigDecimal value) {
return setValue(column, CQL3Type.Name.DECIMAL, value);
}
public PreparedStatement setDouble(int column, double value) {
return setValue(column, CQL3Type.Name.DOUBLE, value);
}
public PreparedStatement setDouble(String column, double value) {
return setValue(column, CQL3Type.Name.DOUBLE, value);
}
public PreparedStatement setFloat(int column, float value) {
return setValue(column, CQL3Type.Name.FLOAT, value);
}
public PreparedStatement setFloat(String column, float value) {
return setValue(column, CQL3Type.Name.FLOAT, value);
}
public PreparedStatement setInt(int column, int value) {
return setValue(column, CQL3Type.Name.INT, value);
}
public PreparedStatement setInt(String column, int value) {
return setValue(column, CQL3Type.Name.INT, value);
}
public PreparedStatement setLong(int column, long value) {
return setValue(column, CQL3Type.Name.BIGINT, value);
}
public PreparedStatement setLong(String column, long value) {
return setValue(column, CQL3Type.Name.BIGINT, value);
}
public PreparedStatement setString(int column, String value) {
return setValue(column, CQL3Type.Name.VARCHAR, CQL3Type.Name.TEXT, CQL3Type.Name.ASCII, value);
}
public PreparedStatement setString(String column, String value) {
return setValue(column, CQL3Type.Name.VARCHAR, CQL3Type.Name.TEXT, CQL3Type.Name.ASCII, value);
}
public PreparedStatement setInet(int column, InetAddress value) {
return setValue(column, CQL3Type.Name.INET, value);
}
public PreparedStatement setInet(String column, InetAddress value) {
return setValue(column, CQL3Type.Name.INET, value);
}
public PreparedStatement setVarint(int column, BigInteger value) {
return setValue(column, CQL3Type.Name.VARINT, value);
}
public PreparedStatement setVarint(String column, BigInteger value) {
return setValue(column, CQL3Type.Name.VARINT, value);
}
public PreparedStatement setUUID(int column, UUID value) {
return setValue(column, CQL3Type.Name.UUID, value);
}
public PreparedStatement setUUID(String column, UUID value) {
return setValue(column, CQL3Type.Name.UUID, value);
}
public PreparedStatement setList(int column, List<?> value) {
return setValue(column, CQL3Type.Name.LIST, value);
}
public PreparedStatement setList(String column, List<?> value) {
return setValue(column, CQL3Type.Name.LIST, value);
}
public PreparedStatement setSet(int column, Set<?> value) {
return setValue(column, CQL3Type.Name.SET, value);
}
public PreparedStatement setSet(String column, Set<?> value) {
return setValue(column, CQL3Type.Name.SET, value);
}
public PreparedStatement setMap(int column, Map<?, ?> value) {
return setValue(column, CQL3Type.Name.MAP, value);
}
public PreparedStatement setMap(String column, Map<?, ?> value) {
return setValue(column, CQL3Type.Name.MAP, value);
}
public PreparedStatement setObject(int column, Object value) {
return setValue(column, getParameterMetadata().getColumnType(column), value);
}
public PreparedStatement setObject(String column, Object value) {
int[] idxs = getParameterMetadata().getColumnIndexArray(column);
ByteBuffer buf = null;
if (value != null) {
CQL3Type columnType = getParameterMetadata().getColumnType(idxs[0]);
for (int i = 1; i < idxs.length; i++) {
getParameterMetadata().validateColumnType(idxs[i], columnType, value);
}
buf = columnType.serialize(value);
}
for (int index : idxs) {
getParameters()[index] = buf;
}
return this;
}
public PreparedStatement bind(Object... values) {
if (values == null) {
throw new NullPointerException("values");
}
if (values.length == 0) {
throw new IllegalArgumentException("empty values");
}
if (values.length > getParameterMetadata().getColumnCount()) {
throw new IllegalArgumentException(String.format("number of bound variables does not match number of parameters: %d (expected: %d)", values.length, getParameterMetadata().getColumnCount()));
}
for (int i = 0; i < values.length; i++) {
setObject(i, values[i]);
}
return this;
}
@Override
public RoutingKey getRoutingKey() {
RoutingKey routingKey = super.getRoutingKey();
if (routingKey != null) {
return routingKey;
}
if (partitionKeyIndexes != null) {
ByteBuffer[] keys = new ByteBuffer[partitionKeyIndexes.length];
for (int i = 0; i < keys.length; i++) {
ByteBuffer value = getParameters()[partitionKeyIndexes[i]];
if (value == null) {
return null;
}
keys[i] = value;
}
routingKey = RoutingKey.copyFrom(keys);
}
return routingKey;
}
@Override
@SuppressWarnings("CloneDoesntCallSuperClone")
public PreparedStatement clone() {
return new PreparedStatement(this);
}
private PreparedStatement setValue(int index, CQL3Type.Name name, Object value) {
return setValue(index, getParameterMetadata().validateColumnType(index, name), value);
}
private PreparedStatement setValue(int index, CQL3Type.Name name1, CQL3Type.Name name2, Object value) {
return setValue(index, getParameterMetadata().validateColumnType(index, name1, name2), value);
}
private PreparedStatement setValue(int index, CQL3Type.Name name1, CQL3Type.Name name2, CQL3Type.Name name3, Object value) {
return setValue(index, getParameterMetadata().validateColumnType(index, name1, name2, name3), value);
}
private PreparedStatement setValue(String column, CQL3Type.Name name, Object value) {
int[] idxs = getParameterMetadata().getColumnIndexArray(column);
CQL3Type columnType = null;
for (int index : idxs) {
columnType = getParameterMetadata().validateColumnType(index, name);
}
return setValue(idxs, columnType, value);
}
private PreparedStatement setValue(String column, CQL3Type.Name name1, CQL3Type.Name name2, Object value) {
int[] idxs = getParameterMetadata().getColumnIndexArray(column);
CQL3Type columnType = null;
for (int index : idxs) {
columnType = getParameterMetadata().validateColumnType(index, name1, name2);
}
return setValue(idxs, columnType, value);
}
private PreparedStatement setValue(String column, CQL3Type.Name name1, CQL3Type.Name name2, CQL3Type.Name name3, Object value) {
int[] idxs = getParameterMetadata().getColumnIndexArray(column);
CQL3Type columnType = null;
for (int index : idxs) {
columnType = getParameterMetadata().validateColumnType(index, name1, name2, name3);
}
return setValue(idxs, columnType, value);
}
private PreparedStatement setValue(int index, CQL3Type columnType, Object value) {
if (value == null) {
getParameters()[index] = null;
} else {
getParameters()[index] = getParameterMetadata().validateColumnType(index, columnType, value).serialize(value);
}
return this;
}
private PreparedStatement setValue(int[] idxs, CQL3Type columnType, Object value) {
ByteBuffer buf = null;
if (value != null) {
buf = getParameterMetadata().validateColumnType(idxs[0], columnType, value).serialize(value);
}
for (int index : idxs) {
getParameters()[index] = buf;
}
return this;
}
}