blob: 5100ba9c8431433436d19ced4731a13c5daf8850 [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.accessor.writer;
import java.math.BigDecimal;
import org.apache.drill.exec.record.metadata.ColumnMetadata;
import org.apache.drill.exec.vector.BaseDataValueVector;
import org.apache.drill.exec.vector.NullableVector;
import org.apache.drill.exec.vector.accessor.ColumnAccessors.UInt1ColumnWriter;
import org.apache.drill.exec.vector.accessor.ColumnWriterIndex;
import org.apache.drill.exec.vector.accessor.ValueType;
import org.apache.drill.exec.vector.accessor.convert.ColumnConversionFactory;
import org.apache.drill.exec.vector.accessor.impl.HierarchicalFormatter;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.joda.time.Period;
public class NullableScalarWriter extends AbstractScalarWriterImpl {
public static final class ChildIndex implements ColumnWriterIndex {
private final ColumnWriterIndex parentIndex;
public ChildIndex(ColumnWriterIndex parentIndex) {
this.parentIndex = parentIndex;
}
@Override
public int rowStartIndex() {
return parentIndex.rowStartIndex();
}
@Override
public int vectorIndex() {
return parentIndex.vectorIndex();
}
@Override
public void nextElement() {
// Ignore next element requests from children.
// Nullable writers have two children, we don't want
// to increment the index twice.
}
@Override
public void prevElement() { }
@Override
public void rollover() {
parentIndex.rollover();
}
@Override
public ColumnWriterIndex outerIndex() {
return parentIndex.outerIndex();
}
}
private final NullableVector nullableVector;
private final UInt1ColumnWriter isSetWriter;
private final BaseScalarWriter baseWriter;
private ColumnWriterIndex writerIndex;
public NullableScalarWriter(ColumnMetadata schema, NullableVector nullableVector, BaseScalarWriter baseWriter) {
this.schema = schema;
this.nullableVector = nullableVector;
isSetWriter = new UInt1ColumnWriter(nullableVector.getBitsVector());
this.baseWriter = baseWriter;
}
public static ScalarObjectWriter build(ColumnMetadata schema,
NullableVector nullableVector, BaseScalarWriter baseWriter,
ColumnConversionFactory conversionFactory) {
return new ScalarObjectWriter(
new NullableScalarWriter(schema, nullableVector, baseWriter),
conversionFactory);
}
public BaseScalarWriter bitsWriter() { return isSetWriter; }
public BaseScalarWriter baseWriter() { return baseWriter; }
@Override
public BaseDataValueVector vector() {
throw new UnsupportedOperationException();
}
@Override
public void bindIndex(ColumnWriterIndex index) {
writerIndex = index;
final ColumnWriterIndex childIndex = new ChildIndex(index);
isSetWriter.bindIndex(childIndex);
baseWriter.bindIndex(childIndex);
}
@Override
public int rowStartIndex() {
return baseWriter.rowStartIndex();
}
@Override
public ValueType valueType() {
return baseWriter.valueType();
}
@Override
public void restartRow() {
isSetWriter.restartRow();
baseWriter.restartRow();
}
@Override
public boolean nullable() { return true; }
@Override
public void setNull() {
isSetWriter.setInt(0);
baseWriter.skipNulls();
writerIndex.nextElement();
}
@Override
public void setBoolean(boolean value) {
baseWriter.setBoolean(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setInt(int value) {
baseWriter.setInt(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setLong(long value) {
baseWriter.setLong(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setDouble(double value) {
baseWriter.setDouble(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setString(String value) {
// String may overflow. Set bits after
// overflow since bits vector does not have
// overflow handling separate from the nullable
// vector as a whole.
baseWriter.setString(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setBytes(byte[] value, int len) {
baseWriter.setBytes(value, len);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void appendBytes(byte[] value, int len) {
baseWriter.appendBytes(value, len);
}
@Override
public void setDecimal(BigDecimal value) {
baseWriter.setDecimal(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setPeriod(Period value) {
baseWriter.setPeriod(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setDate(LocalDate value) {
baseWriter.setDate(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setTime(LocalTime value) {
baseWriter.setTime(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setTimestamp(Instant value) {
baseWriter.setTimestamp(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
@Override
public void setValue(Object value) {
if (value == null) {
setNull();
} else {
baseWriter.setValue(value);
isSetWriter.setInt(1);
writerIndex.nextElement();
}
}
@Override
public void preRollover() {
isSetWriter.preRollover();
baseWriter.preRollover();
}
@Override
public void postRollover() {
isSetWriter.postRollover();
baseWriter.postRollover();
}
@Override
public int lastWriteIndex() {
return baseWriter.lastWriteIndex();
}
@Override
public void bindListener(ColumnWriterListener listener) {
baseWriter.bindListener(listener);
}
@Override
public void startWrite() {
isSetWriter.startWrite();
baseWriter.startWrite();
}
@Override
public void startRow() {
// Skip calls for performance: they do nothing for
// scalar writers -- the only kind supported here.
// isSetWriter.startRow();
baseWriter.startRow();
}
@Override
public void endArrayValue() {
// Skip calls for performance: they do nothing for
// scalar writers -- the only kind supported here.
// isSetWriter.endArrayValue();
baseWriter.endArrayValue();
}
@Override
public void endWrite() {
isSetWriter.endWrite();
// Avoid back-filling null values.
baseWriter.skipNulls();
baseWriter.endWrite();
((NullableVector.Mutator) nullableVector.getMutator())
.setSetCount(writerIndex.vectorIndex());
}
@Override
public void dump(HierarchicalFormatter format) {
format.extend();
super.dump(format);
format.attribute("isSetWriter");
isSetWriter.dump(format);
format.attribute("baseWriter");
baseWriter.dump(format);
format.endObject();
}
@Override
public void setDefaultValue(Object value) {
throw new UnsupportedOperationException(
"Default values not supported for nullable types:" + value);
}
}