Github user paul-rogers commented on a diff in the pull request:
https://github.com/apache/drill/pull/1060#discussion_r158197120
--- 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 --
This is why having the "dupness" being a runtime state is an awkward
approach.
Imagine SVR or flatten. We have to copy values from one vector to another.
Code gen will have to handle the dup/non-dup cases. If it simply does the
"dumb" thing and copies each value an error will result.
---