/** * 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. */ import org.apache.drill.exec.store.AbstractRecordWriter; import java.lang.Override; import java.lang.UnsupportedOperationException; <@pp.dropOutputFile /> <@pp.changeOutputFile name="org/apache/drill/exec/store/StringOutputRecordWriter.java" /> <#include "/@includes/license.ftl" /> package org.apache.drill.exec.store; import com.google.common.collect.Lists; import org.apache.drill.exec.expr.TypeHelper; import org.apache.drill.exec.expr.holders.*; import org.apache.drill.exec.memory.BufferAllocator; import org.apache.drill.exec.record.BatchSchema; import org.apache.drill.exec.record.VectorAccessible; import org.apache.drill.exec.store.EventBasedRecordWriter.FieldConverter; import org.apache.drill.exec.vector.*; import org.apache.drill.exec.vector.complex.reader.FieldReader; import java.io.IOException; import java.lang.UnsupportedOperationException; import java.util.List; import java.util.Map; /** * Abstract implementation of RecordWriter interface which exposes interface: * {@link #writeHeader(List)} * {@link #addField(int,String)} * to output the data in string format instead of implementing addField for each type holder. * * This is useful for text format writers such as CSV, TSV etc. * * NB: Source code generated using FreeMarker template ${.template_name} */ public abstract class StringOutputRecordWriter extends AbstractRecordWriter { private final BufferAllocator allocator; protected StringOutputRecordWriter(BufferAllocator allocator){ this.allocator = allocator; } @Override public void updateSchema(VectorAccessible batch) throws IOException { BatchSchema schema = batch.getSchema(); List<String> columnNames = Lists.newArrayList(); for (int i=0; i < schema.getFieldCount(); i++) { columnNames.add(schema.getColumn(i).getLastName()); } startNewSchema(columnNames); } @Override public FieldConverter getNewMapConverter(int fieldId, String fieldName, FieldReader reader) { throw new UnsupportedOperationException(); } public FieldConverter getNewRepeatedMapConverter(int fieldId, String fieldName, FieldReader reader) { throw new UnsupportedOperationException(); } public FieldConverter getNewRepeatedListConverter(int fieldId, String fieldName, FieldReader reader) { throw new UnsupportedOperationException(); } <#list vv.types as type> <#list type.minor as minor> <#list vv.modes as mode> @Override public FieldConverter getNew${mode.prefix}${minor.class}Converter(int fieldId, String fieldName, FieldReader reader) { return new ${mode.prefix}${minor.class}StringFieldConverter(fieldId, fieldName, reader); } public class ${mode.prefix}${minor.class}StringFieldConverter extends FieldConverter { <#if mode.prefix == "Repeated"> private Repeated${minor.class}Holder holder = new Repeated${minor.class}Holder(); <#else> private Nullable${minor.class}Holder holder = new Nullable${minor.class}Holder(); </#if> public ${mode.prefix}${minor.class}StringFieldConverter(int fieldId, String fieldName, FieldReader reader) { super(fieldId, fieldName, reader); } @Override public void writeField() throws IOException { <#if mode.prefix == "Nullable" > if (!reader.isSet()) { addField(fieldId, null); return; } <#elseif mode.prefix == "Repeated" > throw new UnsupportedOperationException("Repeated types are not supported."); } } <#break> </#if> reader.read(holder); <#if minor.class == "TinyInt" || minor.class == "UInt1" || minor.class == "UInt2" || minor.class == "SmallInt" || minor.class == "Int" || minor.class == "UInt4" || minor.class == "Float4" || minor.class == "BigInt" || minor.class == "UInt8" || minor.class == "Float8"> addField(fieldId, String.valueOf(holder.value)); <#elseif minor.class == "Bit"> addField(fieldId, holder.value == 0 ? "false" : "true"); <#elseif minor.class == "Date" || minor.class == "Time" || minor.class == "TimeTZ" || minor.class == "TimeStamp" || minor.class == "IntervalYear" || minor.class == "IntervalDay" || minor.class == "Interval" || minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse"> // TODO: error check addField(fieldId, reader.readObject().toString()); <#elseif minor.class == "VarChar" || minor.class == "Var16Char" || minor.class == "VarBinary"> addField(fieldId, reader.readObject().toString()); <#else> throw new UnsupportedOperationException(String.format("Unsupported field type: %s"), holder.getCanonicalClass()); </#if> } } </#list> </#list> </#list> public void cleanup() throws IOException { } public abstract void startNewSchema(List<String> columnNames) throws IOException; public abstract void addField(int fieldId, String value) throws IOException; }