/* * 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. */ <@pp.dropOutputFile /> <#list cast.types as type> <#if type.major == "DecimalSimpleVarChar"> <#-- Cast function template for conversion from Decimal9, Decimal18 to VarChar --> <@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" /> <#include "/@includes/license.ftl" /> package org.apache.drill.exec.expr.fn.impl.gcast; <#include "/@includes/vv_imports.ftl" /> import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; import org.apache.drill.exec.expr.holders.*; import org.apache.drill.exec.record.RecordBatch; import org.apache.drill.exec.util.DecimalUtility; import org.apache.drill.exec.expr.annotations.Workspace; import io.netty.buffer.ByteBuf; import io.netty.buffer.DrillBuf; import io.netty.buffer.SwappedByteBuf; import java.nio.ByteBuffer; /* * This class is generated using freemarker and the ${.template_name} template. */ @SuppressWarnings("unused") @FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, returnType = FunctionTemplate.ReturnType.STRING_CAST, nulls = NullHandling.NULL_IF_NULL) public class Cast${type.from}${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; @Param BigIntHolder len; @Inject DrillBuf buffer; @Output ${type.to}Holder out; public void setup() { buffer = buffer.reallocIfNeeded(${type.bufferSize}); } public void eval() { StringBuilder str = new StringBuilder(); if (in.value < 0) { // Negative value, add '-' to the string str.append("-"); // Negate the number in.value *= -1; } ${type.javatype} separator = (${type.javatype}) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale); str.append(in.value / separator); if (in.scale > 0) { str.append("."); String fractionalPart = String.valueOf(in.value % separator); /* Since we are taking modulus to find fractional part, * we will miss printing the leading zeroes in the fractional part * Account for those zeroes * * Eg: 1.0002 * Scale: 3 * * Stored as: 10002 * * We print integer part by 10002/1000 = 1 * We print fractional part by 10002 % 1000 = 2 * * We missed the initial zeroes in the fractional part. Below logic accounts for this case */ str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes((in.value % separator), in.scale)); } out.buffer = buffer; out.start = 0; out.end = Math.min((int)len.value, str.length()); // truncate if target type has length smaller than that of input's string out.buffer.setBytes(0, String.valueOf(str.substring(0,out.end)).getBytes()); } } <#elseif type.major == "DecimalComplexVarChar"> <#-- Cast function template for conversion from Decimal28Sparse, Decimal38Sparse to VarChar --> <@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" /> <#include "/@includes/license.ftl" /> package org.apache.drill.exec.expr.fn.impl.gcast; <#include "/@includes/vv_imports.ftl" /> import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; import org.apache.drill.exec.expr.holders.*; import org.apache.drill.exec.record.RecordBatch; import org.apache.drill.exec.util.DecimalUtility; import org.apache.drill.exec.expr.annotations.Workspace; import io.netty.buffer.ByteBuf; import java.nio.ByteBuffer; /* * This class is generated using freemarker and the ${.template_name} template. */ @SuppressWarnings("unused") @FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, returnType = FunctionTemplate.ReturnType.STRING_CAST, nulls = NullHandling.NULL_IF_NULL) public class Cast${type.from}${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; @Param BigIntHolder len; @Inject DrillBuf buffer; @Output ${type.to}Holder out; public void setup() { buffer = buffer.reallocIfNeeded((int) len.value); } public void eval() { StringBuilder str = new StringBuilder(); int index = 0; int fractionalStartIndex = ${type.arraySize} - org.apache.drill.exec.util.DecimalUtility.roundUp(in.scale); // Find the first non-zero value in the integer part of the decimal while (index < fractionalStartIndex && in.getInteger(index, in.start, in.buffer) == 0) { index++; } // If we have valid digits print '-' sign if ((in.getSign(in.start, in.buffer) == true) && index < ${type.arraySize}) { str.append("-"); } // If all the integer digits are zero, print a single zero if (index == fractionalStartIndex) { str.append("0"); } boolean fillZeroes = false; // convert the integer part while (index < fractionalStartIndex) { int value = in.getInteger(index++, in.start, in.buffer); if (fillZeroes == true) { str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(value, org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS)); } else { str.append(value); fillZeroes = true; } //str.append(value); } if (fractionalStartIndex < ${type.arraySize}) { // We have fractional part, print '.' str.append("."); /* convert the fractional part (except the last decimal digit, * as it might have padding that needs to be stripped */ while (fractionalStartIndex < ${type.arraySize} - 1) { int value = in.getInteger(fractionalStartIndex++, in.start, in.buffer); // Fill zeroes at the beginning of the decimal digit str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(value, org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS)); } // Last decimal digit, strip the extra zeroes we may have padded int actualDigits = in.scale % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS; int lastFractionalDigit = in.getInteger(${type.arraySize} - 1, in.start, in.buffer); if (actualDigits != 0) { // Strip padded zeroes at the end that is not part of the scale lastFractionalDigit /= (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) (org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - actualDigits))); str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(lastFractionalDigit, actualDigits)); } else { // Last digit does not have any padding print as is str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(lastFractionalDigit, org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS)); } } out.buffer = buffer; out.start = 0; out.end = Math.min((int)len.value, str.length()); // truncate if target type has length smaller than that of input's string out.buffer.setBytes(0, String.valueOf(str.substring(0,out.end)).getBytes()); } } </#if> <#-- type.major --> </#list>