public interface UserDefinedWindowFunctionAdapterFactory
UserDefinedWindowFunctionAdapter
for
a given window function call.
When a query string with a reference to a user-defined window function is translated into an executable query, the
parser first looks-up the window function factory for the given function identifier and calls
getSignature(FieldMetaData[], JavaTypes.Type[], Object[])
to determine, whether or not that factory can provide a window function adapter for the given input
parameters. If this check fails, the whole query is already rejected by the query parser.
If however the check succeeded the query translator later on uses the same factory and calls
createInstance(FieldMetaData[], JavaTypes.Type[], Object[])
to actually create an instance of a suitable UserDefinedWindowFunctionAdapter
.
Registration of a UserDefinedWindowFunctionAdapterFactory
at the engine bears the following advantages over
registration of a UserDefinedWindowFunctionAdapter
:
FIRST_VALUE(Type.INTEGER value) -> Type.INTEGER,
FIRST_VALUE(Type.INTEGER value, Type.INTEGER default) -> Type.INTEGER,
FIRST_VALUE(Type.BIG_DECIMAL value) -> Type.BIG_DECIMAL,
FIRST_VALUE(Type.BIG_DECIMAL value, Type.BIG_DECIMAL default) -> Type.BIG_DECIMAL,
FIRST_VALUE(Type.DOUBLE value) -> Type.DOUBLE,
FIRST_VALUE(Type.DOUBLE value, Type.DOUBLE default) -> Type.DOUBLE,
FIRST_VALUE(Type.BIG_DECIMAL value) -> Type.BIG_DECIMAL,
FIRST_VALUE(Type.BIG_DECIMAL value, Type.BIG_DECIMAL default) -> Type.BIG_DECIMAL,
UserDefinedWindowFunctionAdapterFactory
may also take static instantiation parameters into account.
The values of such parameters are constant and are already present at parse time (see UserDefinedFunctionAdapterFactory
documentation for an example).
FIRST_VALUE
function, overloads it for any arbitrary type and
also provides alternative signatures which allow to specify the defaultValue that is returned in case the
window frame is empty for a particular record (e.g. the window frame specification OVER(...ROWS BETWEEN 10 PRECEDING AND 5 PRECEDING)
will always be empty for the first 5 records of a partition). Note, how the factory does all the input parameter checks
and than simply instantiates a generic function adapter. This is not equivalent to registering a single generic
adapter at the engine which takes input parameters of type JavaTypes.Type.UNKNOWN
. This single adapter could
have been called on a string column and returned an integer as defaultValue as none of the checks employed in
the factory below applied.
public static class FirstValue implements UserDefinedWindowFunctionAdapterFactory { public static final class FirstValueAdapter implements UserDefinedWindowFunctionAdapter<Serializable, Object>
{ private final Type[] parameterTypes; public FirstValueAdapter(Type[] parameterTypes) { this.parameterTypes = parameterTypes; }@Override
public Type getReturnType() { return parameterTypes[0]; }@Override
public Type[] getParameterTypes() { return parameterTypes; }@Override
public Serializable createInitialState() { return null; }@Override
public WindowFunctionResultcall(Serializable state, PartitionEntry currentEntry, Partition partition, int currentIndex, WindowFrame currentWindowSpec, WindowFrame previousWindowSpec) { final Serializable[] columnValues = currentEntry.getColumnValues(); final Serializable defaultValue = columnValues.length > 1 ? columnValues[1] : null; if (currentWindowSpec.isEmpty()) return Adapters. <Serializable, Object>
createWindowFunctionResult(null, defaultValue); return Adapters.<Serializable, Object>
createWindowFunctionResult(null, partition.get(currentWindowSpec.getStartIndex()).getColumnValue(0)); }@Override
public void checkWindowSpecification(boolean isPartitioned, boolean isOrdered, WindowFrameSpecification windowFrameSpecification) throws IncompatibleWindowSpecificationException { // no restrictions on the window specification } }@Override
public Signature getSignature(FieldMetaData[] parameterMetaData, Type[] instantiationParameterTypes, Object[] instantiationParameters) throws UserDefinedWindowFunctionException { final Type[] parameterTypes = FieldMetaDatas.getJavaTypes(parameterMetaData); if (parameterTypes.length < 1 || parameterTypes.length > 2 || instantiationParameters.length != 0) throw new UserDefinedWindowFunctionException("Expects at least one and at most two input parameters and no instantiation parameters."); if (parameterTypes.length > 1 && !parameterTypes[0].equals(parameterTypes[1])) throw new UserDefinedWindowFunctionException("Both parameters need to have the same parameter type. Found " + parameterTypes[0] + " and " + parameterTypes[1]); return Adapters.createSignature(parameterTypes[0], parameterTypes);@Override
public UserDefinedWindowFunctionAdaptercreateInstance(FieldMetaData[] parameterMetaData, Type[] instantiationParameterTypes, Object[] instantiationParameters) { return new FirstValueAdapter(FieldMetaDatas.getJavaTypes(parameterMetaData)); } @Override
public void checkWindowSpecification(boolean isPartitioned, boolean isOrdered, WindowFrameSpecification windowFrameSpecification) throws IncompatibleWindowSpecificationException { // no restrictions on the window specification } }
Modifier and Type | Method and Description |
---|---|
void |
checkWindowSpecification(boolean isPartitioned,
boolean isOrdered,
WindowFrameSpecification windowFrameSpecification)
Checks whether or not the window function adapters created by this factory may operate over the given window specification and throws an
IncompatibleWindowSpecificationException
if the check failed. |
UserDefinedWindowFunctionAdapter<?,?> |
createInstance(FieldMetaData[] parameterMetaData,
JavaTypes.Type[] instantiationParameterTypes,
Object[] instantiationParameters)
Instantiates a
UserDefinedWindowFunctionAdapter for the given runtime parameter types and instantiation parameters. |
Signature |
getSignature(FieldMetaData[] parameterMetaData,
JavaTypes.Type[] instantiationParameterTypes,
Object[] instantiationParameters)
Determines, whether or not this factory is able to instantiate a
UserDefinedWindowFunctionAdapter for
the given runtime parameter types and the additional instantiation parameter types and values. |
Signature getSignature(FieldMetaData[] parameterMetaData, JavaTypes.Type[] instantiationParameterTypes, Object[] instantiationParameters) throws UserDefinedWindowFunctionException
UserDefinedWindowFunctionAdapter
for
the given runtime parameter types and the additional instantiation parameter types and values. If an
adapter could be instantiated, the exact Signature
of this function adapter is returned, otherwise
an UserDefinedWindowFunctionException
is thrown.
call(Serializable, PartitionEntry, Partition, int, WindowFrame, WindowFrame)
method using the UserDefinedWindowFunctionAdapter.PartitionEntry
abstraction. Besides the parameter type, the FieldMetaData
object
corresponding to each runtime parameters offers additional information, e.g. the name of the parameter or flags
describing the "null-ability" and case-sensitivity of the parameter.
createInstance(FieldMetaData[], JavaTypes.Type[], Object[])
method so that the concrete adapter instance can be created depending on those instantiation parameters. Their types
and values are also given to getSignature(FieldMetaData[], JavaTypes.Type[], Object[])
so
that the decision, whether or not an adapter could be instantiated, can also take those information into account.parameterMetaData
- An array of FieldMetaData
objects describing the runtime parameters that the
adapter should be able to acceptinstantiationParameterTypes
- The instantiation parameter types that a matching window function adapter is to be
searched forinstantiationParameters
- The actual values of the instantiation parameters.Signature
object describing the actual parameters types, instantiation parameter types and the return
type of the adapter that this factory would return for the given arguments.
UserDefinedWindowFunctionException
- if this factory would not be able to instantiate a UserDefinedWindowFunctionAdapter
for the given argumentsUserDefinedWindowFunctionAdapter<?,?> createInstance(FieldMetaData[] parameterMetaData, JavaTypes.Type[] instantiationParameterTypes, Object[] instantiationParameters)
UserDefinedWindowFunctionAdapter
for the given runtime parameter types and instantiation parameters.
If getSignature(FieldMetaData[], JavaTypes.Type[], Object[])
did not throw an UserDefinedWindowFunctionException
, calling createInstance()
with the same arguments
shall succeed and return a valid adapter.
getSignature(FieldMetaData[], JavaTypes.Type[], Object[])
failed with an
UserDefinedWindowFunctionException
, createInstance()
will equally fail with a corresponding
RuntimeException
.parameterMetaData
- An array of FieldMetaData
objects describing the runtime parameters that the
adapter should be able to acceptinstantiationParameterTypes
- The instantiation parameter typesinstantiationParameters
- The actual values of the instantiation parameters.UserDefinedWindowFunctionAdapter
objectvoid checkWindowSpecification(boolean isPartitioned, boolean isOrdered, WindowFrameSpecification windowFrameSpecification) throws IncompatibleWindowSpecificationException
IncompatibleWindowSpecificationException
if the check failed. Otherwise, the method is expected to return with no errors. This check is independent of the concrete parameters of the window function and is guaranteed to be called
before any call to getSignature(FieldMetaData[], JavaTypes.Type[], Object[])
or
createInstance(FieldMetaData[], JavaTypes.Type[], Object[])
.isPartitioned
- true
if the input source fed into the window function is partitioned, otherwise false
isOrdered
- true
if the input source fed into the window function is ordered, otherwise false
windowFrameSpecification
- determines the specified frame bounds defining the (sliding) window over the input sourceIncompatibleWindowSpecificationException
- if the given window specifications do not satisfy the restrictions imposed by the window function