blob: b116aaec9cff60575511eb6edb07c52aadd4d516 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.drill.exec.vector.complex.impl;
import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.exec.expr.fn.impl.DateUtility;
import org.apache.drill.exec.expr.holders.ValueHolder;
import org.apache.drill.exec.util.Text;
import org.apache.drill.exec.vector.ValueVector;
import org.apache.drill.exec.vector.complex.DictVector;
import org.apache.drill.exec.vector.complex.reader.BaseReader.DictReader;
import org.apache.drill.exec.vector.complex.reader.FieldReader;
import org.apache.drill.exec.vector.complex.writer.BaseWriter.ListWriter;
import org.apache.drill.exec.vector.complex.writer.BaseWriter.DictWriter;
import org.apache.drill.exec.vector.complex.writer.FieldWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class SingleDictReaderImpl extends AbstractRepeatedMapReaderImpl<DictVector> implements DictReader {
public static final int NOT_FOUND = -1;
public SingleDictReaderImpl(DictVector vector) {
super(vector);
}
@Override
public FieldReader reader(String name){
assert DictVector.fieldNames.contains(name);
return super.reader(name);
}
@Override
public int find(String key) {
Object typifiedKey = getAppropriateKey(key);
return find(typifiedKey);
}
@Override
public int find(int key) {
Object typifiedKey = getAppropriateKey(key);
return find(typifiedKey);
}
@Override
public int find(Object key) {
int start = vector.getOffsetVector().getAccessor().get(idx());
int end = vector.getOffsetVector().getAccessor().get(idx() + 1);
int index = NOT_FOUND;
ValueVector keys = vector.getKeys();
// start from the end to ensure the most recent value for a key is found (in case if key is not unique)
for (int i = end - 1; i >= start; i--) {
Object keyValue = keys.getAccessor().getObject(i);
if (keyValue.equals(key)) {
index = i;
break;
}
}
return index;
}
private Object getAppropriateKey(int key) {
TypeProtos.MajorType keyType = vector.getKeyType();
switch (keyType.getMinorType()) {
case SMALLINT:
return (short) key;
case INT:
return key;
case BIGINT:
return (long) key;
case FLOAT4:
return (float) key;
case FLOAT8:
return (double) key;
case VARDECIMAL:
return BigDecimal.valueOf(key)
.setScale(keyType.getScale(), RoundingMode.HALF_UP);
case BIT:
return key != 0;
case VARCHAR:
case VARBINARY:
return new Text(String.valueOf(key));
default:
String message = String.format("Unknown value %d for key of type %s", key, keyType.getMinorType().toString());
throw new IllegalArgumentException(message);
}
}
private Object getAppropriateKey(String key) {
TypeProtos.MajorType keyType = vector.getKeyType();
switch (keyType.getMinorType()) {
case VARCHAR:
case VARBINARY:
return new Text(key);
case BIT:
return Boolean.valueOf(key);
case SMALLINT:
return Short.valueOf(key);
case INT:
return Integer.valueOf(key);
case BIGINT:
return Long.valueOf(key);
case FLOAT4:
return Float.valueOf(key);
case FLOAT8:
return Double.valueOf(key);
case VARDECIMAL:
return BigDecimal.valueOf(Double.valueOf(key))
.setScale(keyType.getScale(), RoundingMode.HALF_UP);
case TIMESTAMP:
return DateUtility.parseBest(key);
case DATE:
return DateUtility.parseLocalDate(key);
case TIME:
return DateUtility.parseLocalTime(key);
default:
String message = String.format("Unknown value %s for key of type %s", key, keyType.getMinorType().toString());
throw new IllegalArgumentException(message);
}
}
@Override
public void read(String key, ValueHolder holder) {
Object typifiedKey = getAppropriateKey(key);
read(typifiedKey, holder);
}
@Override
public void read(int key, ValueHolder holder) {
Object typifiedKey = getAppropriateKey(key);
read(typifiedKey, holder);
}
@Override
public void read(Object key, ValueHolder holder) {
if (isEmpty()) {
return;
}
int index = find(key);
FieldReader valueReader = reader(DictVector.FIELD_VALUE_NAME);
valueReader.setPosition(index);
if (index != NOT_FOUND) {
valueReader.read(holder);
}
}
@Override
public void setPosition(int index) {
if (index == NOT_FOUND) {
for (FieldReader reader : fields.values()) {
reader.setPosition(index);
}
}
super.setPosition(index);
}
@Override
public void copyAsValue(DictWriter writer) {
if (isEmpty()) {
return;
}
ComplexCopier.copy(this, (FieldWriter) writer);
}
@Override
public void copyAsValue(ListWriter writer) {
ComplexCopier.copy(this, (FieldWriter) writer.dict());
}
@Override
public String getTypeString() {
StringBuilder sb = new StringBuilder(super.getTypeString());
// child readers may be empty so vector is used instead to get key and value type
if (vector.getKeyType() != null && vector.getValueType() != null) {
sb.append('<')
.append(vector.getKeyType().getMinorType().name())
.append(',')
.append(vector.getValueType().getMinorType().name())
.append('>');
}
return sb.toString();
}
public MinorType getVectorType() {
return vector.getField().getType().getMinorType();
}
}