Github user sachouche commented on a diff in the pull request: https://github.com/apache/drill/pull/1060#discussion_r162828863 --- Diff: exec/vector/src/main/codegen/templates/NullableValueVectors.java --- @@ -68,96 +85,441 @@ private final UInt1Vector bits = new UInt1Vector(bitsField, allocator); private final ${valuesName} values = new ${minor.class}Vector(field, allocator); + private final Mutator mutator = new MutatorImpl(); + private final Accessor accessor = new AccessorImpl(); + + <#if type.major == "VarLen" && minor.class == "VarChar"> + private final Mutator dupMutator = new DupValsOnlyMutator(); + /** Accessor instance for duplicate values vector */ + private final Accessor dupAccessor = new DupValsOnlyAccessor(); + /** Optimization for cases where all values are identical */ + private boolean duplicateValuesOnly; + /** logical number of values */ + private int logicalNumValues; + /** logical value capacity */ + private int logicalValueCapacity; + /** Mutator instance for duplicate values vector */ + + /** true if this vector holds the same value albeit repeated */ + public boolean isDuplicateValsOnly() { + return duplicateValuesOnly; + } - private final Mutator mutator = new Mutator(); - private final Accessor accessor = new Accessor(); + /** + * Sets this vector duplicate values mode; the {@link #clear()} method wil also be called as a side effect + * of this operation + */ + public void setDuplicateValsOnly(boolean valsOnly) { + clear(); + duplicateValuesOnly = valsOnly; + } - public ${className}(MaterializedField field, BufferAllocator allocator) { - super(field, allocator); + /** {@inheritDoc} */ + @Override + public int getValueCapacity(){ + if (!isDuplicateValsOnly()) { + return Math.min(bits.getValueCapacity(), values.getValueCapacity()); + } + return logicalValueCapacity; } + /** {@inheritDoc} */ @Override - public FieldReader getReader(){ - return reader; + public void close() { + bits.close(); + values.close(); + super.close(); } + /** {@inheritDoc} */ @Override - public int getValueCapacity(){ - return Math.min(bits.getValueCapacity(), values.getValueCapacity()); + public void clear() { + bits.clear(); + values.clear(); + super.clear(); + if (isDuplicateValsOnly()) { + logicalNumValues = 0; + logicalValueCapacity = 0; + duplicateValuesOnly = false; + } } + /** {@inheritDoc} */ @Override - public DrillBuf[] getBuffers(boolean clear) { - final DrillBuf[] buffers = ObjectArrays.concat(bits.getBuffers(false), values.getBuffers(false), DrillBuf.class); - if (clear) { - for (final DrillBuf buffer:buffers) { - buffer.retain(1); + public int getBufferSizeFor(final int valueCount) { + assert valueCount >= 0; + + if (valueCount == 0) { + return 0; + } + if (!isDuplicateValsOnly()) { + return values.getBufferSizeFor(valueCount) + bits.getBufferSizeFor(valueCount); + } + return values.getBufferSizeFor(1) + bits.getBufferSizeFor(1); + } + + /** {@inheritDoc} */ + @Override + public ${valuesName} getValuesVector() { + if (!isDuplicateValsOnly()) { + return values; + } + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override + public void setInitialCapacity(int numRecords) { + assert numRecords >= 0; + if (!isDuplicateValsOnly()) { + bits.setInitialCapacity(numRecords); + values.setInitialCapacity(numRecords); + } else { + bits.setInitialCapacity(numRecords > 0 ? 1 : 0); + values.setInitialCapacity(numRecords > 0 ? 1 : 0); + logicalValueCapacity = numRecords; + } + } + + /** {@inheritDoc} */ + @Override + public Accessor getAccessor() { + if (!isDuplicateValsOnly()) { + return accessor; + } + return dupAccessor; + } + + /** {@inheritDoc} */ + @Override + public Mutator getMutator() { + if (!isDuplicateValsOnly()) { + return mutator; + } + return dupMutator; + } + + public void copyFrom(int fromIndex, int thisIndex, Nullable${minor.class}Vector from) { + final Accessor fromAccessor = from.getAccessor(); + if (isDuplicateValsOnly()) { + // We currently don't have a use-case where a target dup-vector is provisioned by a non-dup source vector + assert isDuplicateValsOnly() == from.isDuplicateValsOnly(); + + if (logicalNumValues == from.logicalNumValues) { + return; // NOOP as we only need to copy one entry } - clear(); + getMutator().setValueCount(from.logicalNumValues); + setInitialCapacity(from.logicalValueCapacity); + } + + if (!fromAccessor.isNull(fromIndex)) { + fromIndex = !from.isDuplicateValsOnly() ? fromIndex : 0; + mutator.fillEmpties(thisIndex); + bits.copyFrom(fromIndex, thisIndex, from.bits); + values.copyFrom(fromIndex, thisIndex, from.values); + } + } + + public void copyFromSafe(int fromIndex, int thisIndex, ${minor.class}Vector from) { + // We currently don't have a use-case where a target dup-vector is provisioned by a non-dup source vector --- End diff -- No error will occur as I added runtime rollback. I am also planning to support multiple different values using dictionary encoding.
---