package org.apache.hadoop.hive.cassandra.input; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.cassandra.serde.CassandraLazyFactory; import org.apache.hadoop.hive.serde2.lazy.ByteArrayRef; import org.apache.hadoop.hive.serde2.lazy.LazyObject; import org.apache.hadoop.hive.serde2.lazy.LazyStruct; import org.apache.hadoop.hive.serde2.lazy.objectinspector.LazyMapObjectInspector; import org.apache.hadoop.hive.serde2.lazy.objectinspector.LazySimpleStructObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.StructField; import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; import org.apache.hadoop.io.BytesWritable; import org.apache.hadoop.io.MapWritable; public class LazyCassandraRow extends LazyStruct { static final Log LOG = LogFactory.getLog(LazyCassandraRow.class); private List<String> cassandraColumns; private List<BytesWritable> cassandraColumnsBB; private MapWritable columnMap; private ArrayList<Object> cachedList; public LazyCassandraRow(LazySimpleStructObjectInspector oi) { super(oi); } public void init(MapWritable columnMap, List<String> cassandraColumns, List<BytesWritable> cassandraColumnsBB) { this.columnMap = columnMap; this.cassandraColumns = cassandraColumns; this.cassandraColumnsBB = cassandraColumnsBB; // these should always be equal if (cassandraColumns.size() != cassandraColumnsBB.size()) { throw new IllegalStateException(); } setParsed(false); } private void parse() { if (getFields() == null) { List<? extends StructField> fieldRefs = ((StructObjectInspector) getInspector()) .getAllStructFieldRefs(); setFields(new LazyObject[fieldRefs.size()]); for (int i = 0; i < getFields().length; i++) { String cassandraColumn = this.cassandraColumns.get(i); if (cassandraColumn.endsWith(":")) { // want all columns as a map getFields()[i] = new LazyCassandraCellMap((LazyMapObjectInspector) fieldRefs.get(i).getFieldObjectInspector()); } else { // otherwise only interested in a single column getFields()[i] = CassandraLazyFactory.createLazyObject( fieldRefs.get(i).getFieldObjectInspector()); } } setFieldInited(new boolean[getFields().length]); } Arrays.fill(getFieldInited(), false); setParsed(true); } @Override public Object getField(int fieldID) { if (!getParsed()) { parse(); } return uncheckedGetField(fieldID); } private Object uncheckedGetField(int fieldID) { if (!getFieldInited()[fieldID]) { getFieldInited()[fieldID] = true; ByteArrayRef ref = null; String columnName = cassandraColumns.get(fieldID); BytesWritable columnNameBB = cassandraColumnsBB.get(fieldID); LazyObject obj = getFields()[fieldID]; if (columnName.endsWith(":")) { // user wants all columns as a map // TODO this into a LazyCassandraCellMap return null; } else { // user wants the value of a single column BytesWritable columnValue = (BytesWritable) columnMap.get(columnNameBB); if (columnValue != null) { ref = new ByteArrayRef(); ref.setData(columnValue.getBytes()); } else { return null; } } if (ref != null) { obj.init(ref, 0, ref.getData().length); } } return getFields()[fieldID].getObject(); } /** * Get the values of the fields as an ArrayList. * * @return The values of the fields as an ArrayList. */ @Override public ArrayList<Object> getFieldsAsList() { if (!getParsed()) { parse(); } if (cachedList == null) { cachedList = new ArrayList<Object>(); } else { cachedList.clear(); } for (int i = 0; i < getFields().length; i++) { cachedList.add(uncheckedGetField(i)); } return cachedList; } @Override public Object getObject() { return this; } }