blob: 2124ca42ca17eab30252eab11f6715b34d2897d4 [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.vector.accessor.writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.exec.record.metadata.ColumnMetadata;
import org.apache.drill.exec.vector.NullableVector;
import org.apache.drill.exec.vector.ValueVector;
import org.apache.drill.exec.vector.accessor.ColumnAccessorUtils;
import org.apache.drill.exec.vector.accessor.writer.AbstractArrayWriter.ArrayObjectWriter;
import org.apache.drill.exec.vector.accessor.writer.AbstractScalarWriterImpl.ScalarObjectWriter;
import org.apache.drill.exec.vector.accessor.writer.dummy.DummyArrayWriter;
import org.apache.drill.exec.vector.accessor.writer.dummy.DummyScalarWriter;
import org.apache.drill.exec.vector.complex.RepeatedValueVector;
/**
* Gather generated writer classes into a set of class tables to allow rapid
* run-time creation of writers. Builds the writer and its object writer
* wrapper which binds the vector to the writer.
* <p>
* Compared to the reader factory, the writer factor is a bit more complex
* as it must handle both the projected ("real" writer) and unprojected
* ("dummy" writer) cases. Because of the way the various classes interact,
* it is cleaner to put the factory methods here rather than in the various
* writers, as is done in the case of the readers.
*/
@SuppressWarnings("unchecked")
public class ColumnWriterFactory {
private static final int typeCount = MinorType.values().length;
private static final Class<? extends BaseScalarWriter> requiredWriters[] = new Class[typeCount];
static {
ColumnAccessorUtils.defineRequiredWriters(requiredWriters);
}
public static AbstractObjectWriter buildColumnWriter(ColumnMetadata schema,
ValueVector vector) {
if (vector == null) {
return buildDummyColumnWriter(schema);
}
// Build a writer for a materialized column.
assert schema.type() == vector.getField().getType().getMinorType();
assert schema.mode() == vector.getField().getType().getMode();
switch (schema.type()) {
case GENERIC_OBJECT:
case LATE:
case NULL:
case LIST:
case MAP:
case DICT:
case UNION:
throw new UnsupportedOperationException(schema.type().toString());
default:
switch (schema.mode()) {
case OPTIONAL:
return nullableScalarWriter(schema, (NullableVector) vector);
case REQUIRED:
return requiredScalarWriter(schema, vector);
case REPEATED:
return repeatedScalarWriter(schema, (RepeatedValueVector) vector);
default:
throw new UnsupportedOperationException(schema.mode().toString());
}
}
}
private static ScalarObjectWriter requiredScalarWriter(
ColumnMetadata schema, ValueVector vector) {
final BaseScalarWriter baseWriter = newWriter(vector);
baseWriter.bindSchema(schema);
return new ScalarObjectWriter(baseWriter);
}
private static ScalarObjectWriter nullableScalarWriter(
ColumnMetadata schema, NullableVector vector) {
final BaseScalarWriter baseWriter = newWriter(vector.getValuesVector());
baseWriter.bindSchema(schema);
return NullableScalarWriter.build(schema, vector, baseWriter);
}
private static AbstractObjectWriter repeatedScalarWriter(
ColumnMetadata schema, RepeatedValueVector vector) {
final BaseScalarWriter baseWriter = newWriter(vector.getDataVector());
baseWriter.bindSchema(schema);
return ScalarArrayWriter.build(schema, vector, baseWriter);
}
/**
* Build a writer for a non-projected column.
* @param schema schema of the column
* @return a "dummy" writer for the column
*/
public static AbstractObjectWriter buildDummyColumnWriter(ColumnMetadata schema) {
switch (schema.type()) {
case GENERIC_OBJECT:
case LATE:
case LIST:
case MAP:
case DICT:
case UNION:
throw new UnsupportedOperationException(schema.type().toString());
default:
final ScalarObjectWriter scalarWriter = new ScalarObjectWriter(
new DummyScalarWriter(schema));
switch (schema.mode()) {
case OPTIONAL:
case REQUIRED:
return scalarWriter;
case REPEATED:
return new ArrayObjectWriter(
new DummyArrayWriter(schema, scalarWriter));
default:
throw new UnsupportedOperationException(schema.mode().toString());
}
}
}
public static BaseScalarWriter newWriter(ValueVector vector) {
final MajorType major = vector.getField().getType();
final MinorType type = major.getMinorType();
try {
final Class<? extends BaseScalarWriter> accessorClass = requiredWriters[type.ordinal()];
if (accessorClass == null) {
throw new UnsupportedOperationException(type.toString());
}
final Constructor<? extends BaseScalarWriter> ctor = accessorClass.getConstructor(ValueVector.class);
return ctor.newInstance(vector);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
SecurityException | IllegalArgumentException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
}