| /* |
| * 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 #startNewSchema(BatchSchema)} |
| * {@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 { |
| startNewSchema(batch.getSchema()); |
| } |
| |
| @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" || |
| minor.class == "VarChar" || |
| minor.class == "Var16Char" || |
| minor.class == "VarBinary" || |
| minor.class == "VarDecimal"> |
| // TODO: error check |
| 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(BatchSchema schema) throws IOException; |
| public abstract void addField(int fieldId, String value) throws IOException; |
| } |