use of org.apache.drill.exec.physical.resultSet.impl.UnionState.UnionVectorState in project drill by apache.
the class ColumnBuilder method buildUnion.
/**
* Builds a union column.
* <p>
* The union vector type is not well supported in Drill. The idea is that
* arbitrary operators can absorb schema changes by converting vectors to
* unions so that an operator can handle, say, a nullable int and a varchar.
* In practice, most operators don't support this feature. (Sort does -- but
* does not manage memory for the union case.) In principal, union can't solve
* the problem because ODBC and JDBC don't support unions, and it is easy
* to envision changes that unions won't solve (int and varchar types combining
* in a join column, say.) Still, Drill supports unions, so the code here
* does so. Unions are fully tested in the row set writer mechanism.
*
* @param parent container of vectors
* @param columnSchema implied projection type for the column
* @return column
*/
private ColumnState buildUnion(ContainerState parent, ColumnMetadata columnSchema) {
assert columnSchema.isVariant() && !columnSchema.isArray();
// vectors can be cached.
assert columnSchema.variantSchema().size() == 0;
final UnionVector vector = new UnionVector(columnSchema.schema(), parent.loader().allocator(), null);
// Then the union writer.
final UnionWriterImpl unionWriter = new UnionWriterImpl(columnSchema, vector, null);
final VariantObjectWriter writer = new VariantObjectWriter(unionWriter);
// The union vector state which manages the types vector.
final UnionVectorState vectorState = new UnionVectorState(vector, unionWriter);
// Create the manager for the columns within the union.
final UnionState unionState = new UnionState(parent.loader(), parent.vectorCache().childCache(columnSchema.name()));
// Bind the union state to the union writer to handle column additions.
unionWriter.bindListener(unionState);
// Assemble it all into a union column state.
return new UnionColumnState(parent.loader(), writer, vectorState, unionState);
}
use of org.apache.drill.exec.physical.resultSet.impl.UnionState.UnionVectorState in project drill by apache.
the class ListState method addSecondType.
/**
* Perform the delicate dance of promoting a list vector from a single type to
* a union, while leaving the writer client blissfully ignorant that the underlying
* vector representation just did a radical change. Key tasks:
* <ul>
* <li>Create the new column (type member) requested by the client.</li>
* <li>The List vector currently has a single type. Promote the list to
* a union, adding the existing type (column) as the first union member.</li>
* <li>Initialize the union's type vector with either the type of the existing
* column, or null, depending on the setting of the is-set bits in the existing
* column vector.</li>
* <li>Since we've written values into the union's type vector, mark the
* last-write position in the union vector's type vector writer to reflect
* these writes. (Otherwise, the writer will helpfully zero-fill the previous
* positions as part of it's back-fill handling.</li>
* <li>Replace the single-type shim in the union vector with a full union
* shim.</li>
* <li>Move the existing column writer or the member column across from the
* single-writer shim to the new union shim.</li>
* <li>Augment the list vector's vector state to include a vector state for
* the newly created union vector.</li>
* </ul>
* <p>
* Here, yet again, an editorial comment might be useful. List vectors are
* very strange and not at all well designed for high-speed writing. They are
* too complex; too much can go wrong and there are too many states to handle.
* Not only that, variant types don't play well with a relational model like
* SQL. This code works, but the overall list concept really needs rethinking.
*
* @param colState the column state for the newly added type column; the
* one causing the list to change from single-type to a union
*/
private void addSecondType(ColumnState colState) {
final UnionWriterImpl unionWriter = unionWriter();
final ListVector listVector = listVector();
// Going from one type to a union
// Convert the list from single type to a union,
// moving across the previous type vector.
final int typeFillCount = unionWriter.elementPosition().writeIndex();
final UnionVector unionVector = listVector.convertToUnion(innerCardinality(), typeFillCount);
unionVector.addType(colState.vector());
// Replace the single-type shim with a union shim, copying
// across the existing writer.
final SimpleListShim oldShim = (SimpleListShim) unionWriter.shim();
final UnionVectorShim newShim = new UnionVectorShim(unionVector);
unionWriter.bindShim(newShim);
newShim.addMemberWriter(oldShim.memberWriter());
newShim.initTypeIndex(typeFillCount);
// The union vector will be managed within the list vector state.
// (Do this last because the union vector state expects the union
// writer to be operating in "union mode".
listVectorState().replaceMember(new UnionVectorState(unionVector, unionWriter));
}
Aggregations