blob: 38818916d6fed1ac0d7855a832e0be203ad3b39f [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.physical.resultSet.impl;
import java.util.Collection;
import org.apache.drill.exec.physical.impl.scan.project.projSet.ProjectionSetFactory;
import org.apache.drill.exec.physical.resultSet.ProjectionSet;
import org.apache.drill.exec.physical.resultSet.ResultVectorCache;
import org.apache.drill.exec.record.metadata.ColumnMetadata;
/**
* Abstract representation of a container of vectors: a row, a map, a
* repeated map, a list or a union.
* <p>
* The container is responsible for creating new columns in response
* from a writer listener event. Column creation requires a set of
* four items:
* <ul>
* <li>The value vector (which may be null if the column is not
* projected.</li>
* <li>The writer for the column.</li>
* <li>A vector state that manages allocation, overflow, cleanup
* and other vector-specific tasks.</li>
* <li>A column state which orchestrates the above three items.</li>
* <ul>
*/
public abstract class ContainerState {
protected final LoaderInternals loader;
protected final ProjectionSet projectionSet;
protected ColumnState parentColumn;
/**
* Vector cache for this loader.
* @see {@link OptionBuilder#setVectorCache()}.
*/
protected final ResultVectorCache vectorCache;
public ContainerState(LoaderInternals loader, ResultVectorCache vectorCache, ProjectionSet projectionSet) {
this.loader = loader;
this.vectorCache = vectorCache;
this.projectionSet = projectionSet;
}
public ContainerState(LoaderInternals loader, ResultVectorCache vectorCache) {
this(loader, vectorCache, ProjectionSetFactory.projectAll());
}
public void bindColumnState(ColumnState parentState) {
this.parentColumn = parentState;
}
public abstract int innerCardinality();
protected abstract void addColumn(ColumnState colState);
protected abstract Collection<ColumnState> columnStates();
/**
* Reports whether this container is subject to version management. Version
* management adds columns to the output container at harvest time based on
* whether they should appear in the output batch.
*
* @return <tt>true</tt> if versioned
*/
protected abstract boolean isVersioned();
protected LoaderInternals loader() { return loader; }
public ResultVectorCache vectorCache() { return vectorCache; }
public ProjectionSet projectionSet() { return projectionSet; }
public ColumnState addColumn(ColumnMetadata columnSchema) {
// Create the vector, writer and column state
ColumnState colState = loader.columnBuilder().buildColumn(this, columnSchema);
// Add the column to this container
addColumn(colState);
// Set initial cardinality
colState.updateCardinality(innerCardinality());
// Allocate vectors if a batch is in progress.
if (loader().writeable()) {
colState.allocateVectors();
}
return colState;
}
/**
* In order to allocate the correct-sized vectors, the container must know
* its member cardinality: the number of elements in each row. This
* is 1 for a single map or union, but may be any number for a map array
* or a list. Then,
* this value is recursively pushed downward to compute the cardinality
* of lists of maps that contains lists of maps, and so on.
*/
public void updateCardinality() {
int innerCardinality = innerCardinality();
assert innerCardinality > 0;
for (ColumnState colState : columnStates()) {
colState.updateCardinality(innerCardinality);
}
}
/**
* Start a new batch by shifting the overflow buffers back into the main
* write vectors and updating the writers.
*/
public void startBatch(boolean schemaOnly) {
for (ColumnState colState : columnStates()) {
colState.startBatch(schemaOnly);
}
}
/**
* A column within the row batch overflowed. Prepare to absorb the rest of the
* in-flight row by rolling values over to a new vector, saving the complete
* vector for later. This column could have a value for the overflow row, or
* for some previous row, depending on exactly when and where the overflow
* occurs.
*/
public void rollover() {
for (ColumnState colState : columnStates()) {
colState.rollover();
}
}
/**
* Writing of a row batch is complete, and an overflow occurred. Prepare the
* vector for harvesting to send downstream. Set aside the look-ahead vector
* and put the full vector buffer back into the active vector.
*/
public void harvestWithLookAhead() {
for (ColumnState colState : columnStates()) {
colState.harvestWithLookAhead();
}
}
/**
* Clean up state (such as backup vectors) associated with the state
* for each vector.
*/
public void close() {
for (ColumnState colState : columnStates()) {
colState.close();
}
}
}