blob: 038509168e244593682724b2aac6afdedb509e34 [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.reader;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.exec.vector.accessor.ColumnAccessors.UInt1ColumnReader;
import org.apache.drill.exec.vector.accessor.ColumnReaderIndex;
import org.apache.drill.exec.vector.complex.UnionVector;
public class NullStateReaders {
public static final RequiredStateReader REQUIRED_STATE_READER = new RequiredStateReader();
public static final NullStateReader NULL_STATE_READER = new AlwaysNullStateReader();
private NullStateReaders() { }
/**
* Dummy implementation of a null state reader for cases in which the
* value is never null. Use the {@link NullStateReaders#REQUIRED_STATE_READER} instance
* for this case.
*/
protected static class RequiredStateReader implements NullStateReader {
@Override
public void bindIndex(ColumnReaderIndex rowIndex) { }
@Override
public boolean isNull() { return false; }
}
/**
* Holder for the NullableVector wrapper around a bits vector and a
* data vector. Manages the bits vector to extract the nullability
* value.
* <p>
* This class allows the same reader to handle both the required and
* nullable cases; the only difference is how nulls are handled.
*/
protected static class NullableIsSetVectorStateReader implements NullStateReader {
private final VectorAccessor nullableAccessor;
private final UInt1ColumnReader isSetReader;
public NullableIsSetVectorStateReader(VectorAccessor nullableAccessor) {
this.nullableAccessor = nullableAccessor;
isSetReader = new UInt1ColumnReader();
isSetReader.bindVector(null,
VectorAccessors.nullableBitsAccessor(nullableAccessor));
isSetReader.bindNullState(REQUIRED_STATE_READER);
}
@Override
public void bindIndex(ColumnReaderIndex rowIndex) {
nullableAccessor.bind(rowIndex);
isSetReader.bindIndex(rowIndex);
}
@Override
public boolean isNull() {
return isSetReader.getInt() == 0;
}
}
/**
* Holder for the NullableVector wrapper around a bits vector and a
* data vector. Manages the bits vector to extract the nullability
* value.
* <p>
* This class allows the same reader to handle both the required and
* nullable cases; the only difference is how nulls are handled.
*/
protected static class ListIsSetVectorStateReader implements NullStateReader {
private final VectorAccessor bitsAccessor;
private final UInt1ColumnReader isSetReader;
public ListIsSetVectorStateReader(VectorAccessor bitsAccessor) {
this.bitsAccessor = bitsAccessor;
isSetReader = new UInt1ColumnReader();
isSetReader.bindVector(null, bitsAccessor);
isSetReader.bindNullState(REQUIRED_STATE_READER);
}
@Override
public void bindIndex(ColumnReaderIndex rowIndex) {
bitsAccessor.bind(rowIndex);
isSetReader.bindIndex(rowIndex);
}
@Override
public boolean isNull() {
return isSetReader.getInt() == 0;
}
}
/**
* Null state that handles the strange union semantics that both
* the union and the values can be null. A value is null if either
* the union or the value is null. (Though, presumably, in the normal
* case either the union is null or one of the associated values is
* null.)
*/
protected static class MemberNullStateReader implements NullStateReader {
private final NullStateReader unionNullState;
private final NullStateReader memberNullState;
public MemberNullStateReader(NullStateReader unionNullState, NullStateReader memberNullState) {
this.unionNullState = unionNullState;
this.memberNullState = memberNullState;
}
@Override
public void bindIndex(ColumnReaderIndex rowIndex) {
memberNullState.bindIndex(rowIndex);
}
@Override
public boolean isNull() {
return unionNullState.isNull() || memberNullState.isNull();
}
}
/**
* Handle the awkward situation with complex types. They don't carry their own
* bits (null state) vector. Instead, we define them as null if the type of
* the union is other than the type of the map or list. (Since the same vector
* that holds state also holds the is-null value, this check includes the
* check if the entire union is null.)
*/
protected static class ComplexMemberStateReader implements NullStateReader {
private UInt1ColumnReader typeReader;
private MinorType type;
public ComplexMemberStateReader(UInt1ColumnReader typeReader, MinorType type) {
this.typeReader = typeReader;
this.type = type;
}
@Override
public void bindIndex(ColumnReaderIndex rowIndex) { }
@Override
public boolean isNull() {
return typeReader.getInt() != type.getNumber();
}
}
/**
* Extract null state from the union vector's type vector. The union reader
* manages the type reader, so no binding is done here.
*/
protected static class TypeVectorStateReader implements NullStateReader {
public final UInt1ColumnReader typeReader;
public TypeVectorStateReader(UInt1ColumnReader typeReader) {
this.typeReader = typeReader;
}
@Override
public void bindIndex(ColumnReaderIndex rowIndex) {
typeReader.bindIndex(rowIndex);
}
@Override
public boolean isNull() {
return typeReader.getInt() == UnionVector.NULL_MARKER;
}
}
protected static class AlwaysNullStateReader implements NullStateReader {
@Override
public void bindIndex(ColumnReaderIndex rowIndex) {
}
@Override
public boolean isNull() {
return true;
}
}
}