blob: 0e0a48abba3b8ba3e6e41e7ea1392470871ece2d [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.expr.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.exec.expr.fn.FunctionAttributes;
import org.apache.drill.exec.expr.fn.output.ConcatReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.DecimalReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.DefaultReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.OutputWidthCalculator;
import org.apache.drill.exec.expr.fn.output.OutputWidthCalculators;
import org.apache.drill.exec.expr.fn.output.PadReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.ReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.SameInOutLengthReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.StringCastReturnTypeInference;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface FunctionTemplate {
/**
* Name of function (when only one.)
* Use this annotation element if there is only one name for the function.
* Note: If you use this annotation don't use {@link #names()}.
* <p>
* TODO: Refer to wherever list of possible or at least known names is,
* to resolve the current issue of spaces vs. underlines in names (e.g., we
* have both "less_than" and "less than".
* </p>
* @return function name
*/
String name() default "";
/**
* Names of function (when multiple).
* Use this annotation element if there are multiple names for the function.
* Note: If you use this annotation don't use {@link #name()}.
* <p>
* TODO: Refer to wherever list of possible or at least known names is,
* to resolve the current issue of spaces vs. underlines in names (e.g., we
* have both "less_than" and "less than".
* </p>
* @return list of function names
*/
String[] names() default {};
FunctionScope scope();
ReturnType returnType() default ReturnType.DEFAULT;
NullHandling nulls() default NullHandling.INTERNAL;
boolean isBinaryCommutative() default false;
boolean isRandom() default false;
String desc() default "";
FunctionCostCategory costCategory() default FunctionCostCategory.SIMPLE;
/**
* <p>Set Operand type-checking strategy for an operator which takes no operands
* and need to be invoked without parentheses. E.g.: session_id is a niladic
* function.</p>
*
* <p>Niladic functions override columns that have names same as any niladic
* function. Such columns cannot be queried without the table qualification.
* Value of the niladic function is returned when table qualification is not
* used.</p>
*
* <p>For e.g. in the case of session_id:<br/>
* select session_id from table -> returns the value of niladic function
* session_id<br/>
* select t1.session_id from table t1 -> returns session_id column value from
* table</p>
*/
boolean isNiladic() default false;
boolean checkPrecisionRange() default false;
/**
* Defines if a function is internal and not intended for public use [e.g. castEmptyStringNullableVarBinaryToNullableVarDecimal(..) ]
*/
boolean isInternal() default false;
/**
* Defines if a function accepts variable arguments count
*/
boolean isVarArg() default false;
/**
* Estimates the average size of the output
* produced by a function that produces variable length output
*/
enum OutputWidthCalculatorType {
DEFAULT(OutputWidthCalculators.DefaultOutputWidthCalculator.INSTANCE),
CLONE(OutputWidthCalculators.CloneOutputWidthCalculator.INSTANCE),
CONCAT(OutputWidthCalculators.ConcatOutputWidthCalculator.INSTANCE),
// Custom calculator is required for functions that don't fall into any predefined
// calculator categories - like replace and lpad
// place holder markers on functions until support
// for CUSTOM calculators is implemented
// CUSTOM_FIXED_WIDTH_DEFAULT will default to a fixed size - for functions like
// lpad() where the ouput size does not easily map to the input size
CUSTOM_FIXED_WIDTH_DEFAULT(OutputWidthCalculators.DefaultOutputWidthCalculator.INSTANCE),
// CUSTOM CLONE will default to CLONE - for functions like replace() where the output
// size does not easily map to the input size but is likely to be at most the size of the input.
CUSTOM_CLONE_DEFAULT(OutputWidthCalculators.CloneOutputWidthCalculator.INSTANCE);
OutputWidthCalculator outputWidthCalculator;
OutputWidthCalculatorType(OutputWidthCalculator outputWidthCalculator) {
this.outputWidthCalculator = outputWidthCalculator;
}
public OutputWidthCalculator getOutputWidthCalculator() { return outputWidthCalculator; }
}
OutputWidthCalculatorType outputWidthCalculatorType() default OutputWidthCalculatorType.DEFAULT;
int OUTPUT_SIZE_ESTIMATE_DEFAULT = -1;
int outputSizeEstimate() default OUTPUT_SIZE_ESTIMATE_DEFAULT;
enum NullHandling {
/**
* Method handles nulls.
*/
INTERNAL,
/**
* Null output if any null input:
* Indicates that a method's associated logical operation returns NULL if
* either input is NULL, and therefore that the method must not be called
* with null inputs. (The calling framework must handle NULLs.)
*
* <p>Not Supported for aggregate functions and for functions with {@link Output} of type
* {@link org.apache.drill.exec.vector.complex.writer.BaseWriter.ComplexWriter}.</p>
*/
NULL_IF_NULL
}
/**
* Function scope is used to indicate function output rows relation:
* simple / scalar (1 -> 1) or aggregate (n -> 1).
*/
enum FunctionScope {
SIMPLE,
POINT_AGGREGATE,
HOLISTIC_AGGREGATE,
RANGE_AGGREGATE
}
/**
* Return type enum is used to indicate which return type calculation logic
* should be used for functions.
*/
enum ReturnType {
DEFAULT(DefaultReturnTypeInference.INSTANCE),
STRING_CAST(StringCastReturnTypeInference.INSTANCE),
CONCAT(ConcatReturnTypeInference.INSTANCE),
PAD(PadReturnTypeInference.INSTANCE),
SAME_IN_OUT_LENGTH(SameInOutLengthReturnTypeInference.INSTANCE),
DECIMAL_AGGREGATE(DecimalReturnTypeInference.DecimalAggReturnTypeInference.INSTANCE),
DECIMAL_SUM_AGGREGATE(DecimalReturnTypeInference.DecimalSumAggReturnTypeInference.INSTANCE),
DECIMAL_AVG_AGGREGATE(DecimalReturnTypeInference.DecimalAvgAggReturnTypeInference.INSTANCE),
DECIMAL_MAX_SCALE(DecimalReturnTypeInference.DecimalMaxScaleReturnTypeInference.INSTANCE),
DECIMAL_SUM_SCALE(DecimalReturnTypeInference.DecimalSumScaleReturnTypeInference.INSTANCE),
DECIMAL_CAST(DecimalReturnTypeInference.DecimalCastReturnTypeInference.INSTANCE),
DECIMAL_DIV_SCALE(DecimalReturnTypeInference.DecimalDivScaleReturnTypeInference.INSTANCE),
DECIMAL_MOD_SCALE(DecimalReturnTypeInference.DecimalModScaleReturnTypeInference.INSTANCE),
DECIMAL_ADD_SCALE(DecimalReturnTypeInference.DecimalAddReturnTypeInference.INSTANCE),
DECIMAL_SET_SCALE(DecimalReturnTypeInference.DecimalSetScaleReturnTypeInference.INSTANCE),
DECIMAL_ZERO_SCALE(DecimalReturnTypeInference.DecimalZeroScaleReturnTypeInference.INSTANCE);
private final ReturnTypeInference inference;
ReturnType(ReturnTypeInference inference) {
this.inference = inference;
}
public TypeProtos.MajorType getType(List<LogicalExpression> logicalExpressions, FunctionAttributes attributes) {
return inference.getType(logicalExpressions, attributes);
}
}
enum FunctionCostCategory {
SIMPLE(1), MEDIUM(20), COMPLEX(50);
private final int value;
FunctionCostCategory(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public static FunctionCostCategory getDefault() {
return SIMPLE;
}
}
}