Repository: drill Updated Branches: refs/heads/master 789b83d77 -> e57514aad
DRILL-5709: Provide a value vector method to convert a vector to nullable Please see the DRILL-5709 for an explanation and example. close apache/drill#901 Project: http://git-wip-us.apache.org/repos/asf/drill/repo Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/6829af09 Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/6829af09 Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/6829af09 Branch: refs/heads/master Commit: 6829af095ac5bb78ed3df874f078891e61ef7721 Parents: 789b83d Author: Paul Rogers <prog...@maprtech.com> Authored: Tue Aug 8 20:04:24 2017 -0700 Committer: Aman Sinha <asi...@maprtech.com> Committed: Sun Sep 3 23:15:07 2017 -0700 ---------------------------------------------------------------------- .../org/apache/drill/vector/TestToNullable.java | 135 +++++++++++++++++++ .../codegen/templates/FixedValueVectors.java | 6 + .../codegen/templates/NullableValueVectors.java | 38 +++++- .../src/main/codegen/templates/UnionVector.java | 5 + .../templates/VariableLengthVectors.java | 6 + .../drill/exec/vector/BaseValueVector.java | 20 ++- .../org/apache/drill/exec/vector/BitVector.java | 6 + .../drill/exec/vector/NullableVector.java | 3 +- .../apache/drill/exec/vector/ObjectVector.java | 5 + .../apache/drill/exec/vector/ValueVector.java | 13 ++ .../apache/drill/exec/vector/ZeroVector.java | 6 + .../drill/exec/vector/complex/MapVector.java | 7 +- .../exec/vector/complex/RepeatedListVector.java | 5 + .../exec/vector/complex/RepeatedMapVector.java | 5 + 14 files changed, 250 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/java-exec/src/test/java/org/apache/drill/vector/TestToNullable.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/test/java/org/apache/drill/vector/TestToNullable.java b/exec/java-exec/src/test/java/org/apache/drill/vector/TestToNullable.java new file mode 100644 index 0000000..234ad88 --- /dev/null +++ b/exec/java-exec/src/test/java/org/apache/drill/vector/TestToNullable.java @@ -0,0 +1,135 @@ +/* + * 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.vector; + +import static org.junit.Assert.*; + +import org.apache.drill.common.types.TypeProtos.DataMode; +import org.apache.drill.common.types.TypeProtos.MinorType; +import org.apache.drill.exec.record.MaterializedField; +import org.apache.drill.exec.vector.IntVector; +import org.apache.drill.exec.vector.NullableIntVector; +import org.apache.drill.exec.vector.NullableVarCharVector; +import org.apache.drill.exec.vector.VarCharVector; +import org.apache.drill.test.SubOperatorTest; +import org.apache.drill.test.rowSet.SchemaBuilder; +import org.bouncycastle.util.Arrays; +import org.junit.Test; + +public class TestToNullable extends SubOperatorTest { + + @SuppressWarnings("resource") + @Test + public void testFixedWidth() { + MaterializedField intSchema = + SchemaBuilder.columnSchema("a", MinorType.INT, DataMode.REQUIRED); + IntVector intVector = new IntVector(intSchema, fixture.allocator()); + IntVector.Mutator intMutator = intVector.getMutator(); + intVector.allocateNew(100); + for (int i = 0; i < 100; i++) { + intMutator.set(i, i * 10); + } + intMutator.setValueCount(100); + + MaterializedField nullableIntSchema = + SchemaBuilder.columnSchema("a", MinorType.INT, DataMode.OPTIONAL); + NullableIntVector nullableIntVector = new NullableIntVector(nullableIntSchema, fixture.allocator()); + + intVector.toNullable(nullableIntVector); + + assertEquals(0, intVector.getAccessor().getValueCount()); + NullableIntVector.Accessor niAccessor = nullableIntVector.getAccessor(); + assertEquals(100, niAccessor.getValueCount()); + for (int i = 0; i < 100; i++) { + assertFalse(niAccessor.isNull(i)); + assertEquals(i * 10, niAccessor.get(i)); + } + + nullableIntVector.clear(); + + // Don't clear the intVector, it should be empty. + // If it is not, the test will fail with a memory leak error. + } + + @SuppressWarnings("resource") + @Test + public void testNullable() { + MaterializedField nullableIntSchema = + SchemaBuilder.columnSchema("a", MinorType.INT, DataMode.OPTIONAL); + NullableIntVector sourceVector = new NullableIntVector(nullableIntSchema, fixture.allocator()); + NullableIntVector.Mutator sourceMutator = sourceVector.getMutator(); + sourceVector.allocateNew(100); + for (int i = 0; i < 100; i++) { + sourceMutator.set(i, i * 10); + } + sourceMutator.setValueCount(100); + + NullableIntVector destVector = new NullableIntVector(nullableIntSchema, fixture.allocator()); + + sourceVector.toNullable(destVector); + + assertEquals(0, sourceVector.getAccessor().getValueCount()); + NullableIntVector.Accessor destAccessor = destVector.getAccessor(); + assertEquals(100, destAccessor.getValueCount()); + for (int i = 0; i < 100; i++) { + assertFalse(destAccessor.isNull(i)); + assertEquals(i * 10, destAccessor.get(i)); + } + + destVector.clear(); + + // Don't clear the intVector, it should be empty. + // If it is not, the test will fail with a memory leak error. + } + + @SuppressWarnings("resource") + @Test + public void testVariableWidth() { + MaterializedField nonNullableSchema = + SchemaBuilder.columnSchema("a", MinorType.VARCHAR, DataMode.REQUIRED); + VarCharVector nonNullableVector = new VarCharVector(nonNullableSchema, fixture.allocator()); + VarCharVector.Mutator mutator = nonNullableVector.getMutator(); + nonNullableVector.allocateNew(100, 20); + byte value[] = new byte[20]; + for (int i = 0; i < 100; i++) { + Arrays.fill(value, (byte)('A' + i % 26)); + mutator.setSafe(i, value); + } + mutator.setValueCount(100); + + MaterializedField nullableVarCharSchema = + SchemaBuilder.columnSchema("a", MinorType.VARCHAR, DataMode.OPTIONAL); + NullableVarCharVector nullableVector = new NullableVarCharVector(nullableVarCharSchema, fixture.allocator()); + + nonNullableVector.toNullable(nullableVector); + + assertEquals(0, nonNullableVector.getAccessor().getValueCount()); + NullableVarCharVector.Accessor nullableAccessor = nullableVector.getAccessor(); + assertEquals(100, nullableAccessor.getValueCount()); + for (int i = 0; i < 100; i++) { + assertFalse(nullableAccessor.isNull(i)); + Arrays.fill(value, (byte)('A' + i % 26)); + assertTrue(Arrays.areEqual(value, nullableAccessor.get(i))); + } + + nullableVector.clear(); + + // Don't clear the nonNullableVector, it should be empty. + // If it is not, the test will fail with a memory leak error. + } +} http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/codegen/templates/FixedValueVectors.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/codegen/templates/FixedValueVectors.java b/exec/vector/src/main/codegen/templates/FixedValueVectors.java index 5a53e21..e8cdcf8 100644 --- a/exec/vector/src/main/codegen/templates/FixedValueVectors.java +++ b/exec/vector/src/main/codegen/templates/FixedValueVectors.java @@ -335,6 +335,12 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements F ++allocationMonitor; } + @Override + public void toNullable(ValueVector nullableVector) { + Nullable${minor.class}Vector dest = (Nullable${minor.class}Vector) nullableVector; + dest.getMutator().fromNotNullable(this); + } + public final class Accessor extends BaseDataValueVector.BaseAccessor { @Override public int getValueCount() { http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/codegen/templates/NullableValueVectors.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/codegen/templates/NullableValueVectors.java b/exec/vector/src/main/codegen/templates/NullableValueVectors.java index a2c0deb..4418212 100644 --- a/exec/vector/src/main/codegen/templates/NullableValueVectors.java +++ b/exec/vector/src/main/codegen/templates/NullableValueVectors.java @@ -133,9 +133,10 @@ public final class ${className} extends BaseDataValueVector implements <#if type } @Override - public ${valuesName} getValuesVector() { - return values; - } + public ${valuesName} getValuesVector() { return values; } + + @Override + public UInt1Vector getBitsVector() { return bits; } @Override public void setInitialCapacity(int numRecords) { @@ -398,6 +399,14 @@ public final class ${className} extends BaseDataValueVector implements <#if type mutator.exchange(other.getMutator()); } + <#if type.major != "VarLen"> + @Override + public void toNullable(ValueVector nullableVector) { + exchange(nullableVector); + clear(); + } + + </#if> public final class Accessor extends BaseDataValueVector.BaseAccessor <#if type.major = "VarLen">implements VariableWidthVector.VariableWidthAccessor</#if> { final UInt1Vector.Accessor bAccessor = bits.getAccessor(); final ${valuesName}.Accessor vAccessor = values.getAccessor(); @@ -449,8 +458,8 @@ public final class ${className} extends BaseDataValueVector implements <#if type @Override public ${friendlyType} getObject(int index) { if (isNull(index)) { - return null; - }else{ + return null; + } else { return vAccessor.getObject(index); } } @@ -458,8 +467,8 @@ public final class ${className} extends BaseDataValueVector implements <#if type <#if minor.class == "Interval" || minor.class == "IntervalDay" || minor.class == "IntervalYear"> public StringBuilder getAsStringBuilder(int index) { if (isNull(index)) { - return null; - }else{ + return null; + } else { return vAccessor.getAsStringBuilder(index); } } @@ -778,6 +787,21 @@ public final class ${className} extends BaseDataValueVector implements <#if type setCount = target.setCount; target.setCount = temp; } + + public void fromNotNullable(${minor.class}Vector srce) { + clear(); + final int valueCount = srce.getAccessor().getValueCount(); + + // Create a new bits vector, all values non-null + + fillBitsVector(getBitsVector(), valueCount); + + // Swap the data portion + + getValuesVector().exchange(srce); + <#if type.major = "VarLen">lastSet = valueCount;</#if> + setValueCount(valueCount); + } } } </#list> http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/codegen/templates/UnionVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/codegen/templates/UnionVector.java b/exec/vector/src/main/codegen/templates/UnionVector.java index 2c732f4..c198544 100644 --- a/exec/vector/src/main/codegen/templates/UnionVector.java +++ b/exec/vector/src/main/codegen/templates/UnionVector.java @@ -267,6 +267,11 @@ public class UnionVector implements ValueVector { return newVector; } + @Override + public void toNullable(ValueVector nullableVector) { + throw new UnsupportedOperationException(); + } + private class TransferImpl implements TransferPair { UnionVector to; http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/codegen/templates/VariableLengthVectors.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java index 0eb8906..4527da8 100644 --- a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java +++ b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java @@ -422,6 +422,12 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V offsetVector.exchange(target.offsetVector); } + @Override + public void toNullable(ValueVector nullableVector) { + Nullable${minor.class}Vector dest = (Nullable${minor.class}Vector) nullableVector; + dest.getMutator().fromNotNullable(this); + } + public final class Accessor extends BaseValueVector.BaseAccessor implements VariableWidthAccessor { final UInt${type.width}Vector.Accessor oAccessor = offsetVector.getAccessor(); public long getStartEnd(int index){ http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/BaseValueVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/BaseValueVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/BaseValueVector.java index f4a5847..2179829 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/BaseValueVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/BaseValueVector.java @@ -19,6 +19,7 @@ package org.apache.drill.exec.vector; import io.netty.buffer.DrillBuf; +import java.util.Collections; import java.util.Iterator; import com.google.common.base.Preconditions; @@ -116,7 +117,7 @@ public abstract class BaseValueVector implements ValueVector { @Override public Iterator<ValueVector> iterator() { - return Iterators.emptyIterator(); + return Collections.emptyIterator(); } public static boolean checkBufRefs(final ValueVector vv) { @@ -133,5 +134,22 @@ public abstract class BaseValueVector implements ValueVector { public BufferAllocator getAllocator() { return allocator; } + + public static void fillBitsVector(UInt1Vector bits, int valueCount) { + + // Create a new bits vector, all values non-null + + bits.allocateNew(valueCount); + UInt1Vector.Mutator bitsMutator = bits.getMutator(); + for (int i = 0; i < valueCount; i++) { + bitsMutator.set(i, 1); + } + bitsMutator.setValueCount(valueCount); + } + + @Override + public void toNullable(ValueVector nullableVector) { + throw new UnsupportedOperationException(); + } } http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/BitVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/BitVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/BitVector.java index a7c81de..4d7098b 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/BitVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/BitVector.java @@ -531,4 +531,10 @@ public final class BitVector extends BaseDataValueVector implements FixedWidthVe public int getPayloadByteCount(int valueCount) { return getSizeFromCount(valueCount); } + + @Override + public void toNullable(ValueVector nullableVector) { + NullableBitVector dest = (NullableBitVector) nullableVector; + dest.getMutator().fromNotNullable(this); + } } http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/NullableVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/NullableVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/NullableVector.java index 8091c4c..51b5e0c 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/NullableVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/NullableVector.java @@ -1,4 +1,4 @@ -/** +/* * 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 @@ -19,5 +19,6 @@ package org.apache.drill.exec.vector; public interface NullableVector extends ValueVector{ + ValueVector getBitsVector(); ValueVector getValuesVector(); } http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/ObjectVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/ObjectVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/ObjectVector.java index 3136e32..c9edeb0 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/ObjectVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/ObjectVector.java @@ -206,6 +206,11 @@ public class ObjectVector extends BaseValueVector { throw new UnsupportedOperationException("ObjectVector does not support this"); } + @Override + public void toNullable(ValueVector nullableVector) { + throw new UnsupportedOperationException(); + } + public final class Accessor extends BaseAccessor { @Override public Object getObject(int index) { http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueVector.java index 2926862..5125626 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueVector.java @@ -228,6 +228,19 @@ public interface ValueVector extends Closeable, Iterable<ValueVector> { void exchange(ValueVector other); /** + * Convert a non-nullable vector to nullable by shuffling the data from + * one to the other. Avoids the need to generate copy code just to change + * mode. If this vector is non-nullable, accepts a nullable dual (same + * minor type, different mode.) If the vector is non-nullable, or non-scalar, + * then throws an exception. + * + * @param nullableVector nullable vector of the same minor type as + * this vector + */ + + void toNullable(ValueVector nullableVector); + + /** * An abstraction that is used to read from this vector instance. */ interface Accessor { http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/ZeroVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/ZeroVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/ZeroVector.java index 5786487..e6f0544 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/ZeroVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/ZeroVector.java @@ -162,8 +162,14 @@ public class ZeroVector implements ValueVector { @Override public void exchange(ValueVector other) { } + @Override public void collectLedgers(Set<BufferLedger> ledgers) {} @Override public int getPayloadByteCount(int valueCount) { return 0; } + + @Override + public void toNullable(ValueVector nullableVector) { + throw new UnsupportedOperationException(); + } } http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/MapVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/MapVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/MapVector.java index f755081..f9ff58d 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/MapVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/MapVector.java @@ -388,5 +388,10 @@ public class MapVector extends AbstractMapVector { valueCount = 0; super.close(); - } + } + + @Override + public void toNullable(ValueVector nullableVector) { + throw new UnsupportedOperationException(); + } } http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedListVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedListVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedListVector.java index ab2c3d8..be9ebee 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedListVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedListVector.java @@ -452,4 +452,9 @@ public class RepeatedListVector extends AbstractContainerVector // TODO: Figure out how to test this scenario, then what to do... throw new UnsupportedOperationException("Exchange() not yet supported for repeated lists"); } + + @Override + public void toNullable(ValueVector nullableVector) { + throw new UnsupportedOperationException(); + } } http://git-wip-us.apache.org/repos/asf/drill/blob/6829af09/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedMapVector.java ---------------------------------------------------------------------- diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedMapVector.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedMapVector.java index be73fc8..999e29e 100644 --- a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedMapVector.java +++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/RepeatedMapVector.java @@ -604,4 +604,9 @@ public class RepeatedMapVector extends AbstractMapVector super.collectLedgers(ledgers); offsets.collectLedgers(ledgers); } + + @Override + public void toNullable(ValueVector nullableVector) { + throw new UnsupportedOperationException(); + } }