| /* |
| * 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); |
| } |
| } |
| } |