Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,13 @@ FunctionHandle resolveFunction(
FunctionHandle lookupCast(String castType, Type fromType, Type toType);

QualifiedObjectName qualifyObjectName(QualifiedName name);

/**
* Validate a function call during analysis phase on the coordinator.
* Delegates to the FunctionNamespaceManager for custom validation logic.
*
* @param functionHandle The function handle being validated
* @param arguments Raw argument expressions (not yet evaluated)
*/
void validateFunctionCall(FunctionHandle functionHandle, List<?> arguments);
}
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,12 @@ public FunctionHandle lookupCast(String castType, Type fromType, Type toType)
return FunctionAndTypeManager.this.lookupCast(CastType.valueOf(castType), fromType, toType);
}

@Override
public void validateFunctionCall(FunctionHandle functionHandle, List<?> arguments)
{
FunctionAndTypeManager.this.validateFunctionCall(functionHandle, arguments);
}

public QualifiedObjectName qualifyObjectName(QualifiedName name)
{
if (name.getSuffix().startsWith("$internal")) {
Expand Down Expand Up @@ -719,6 +725,19 @@ public CompletableFuture<SqlFunctionResult> executeFunction(String source, Funct
return functionNamespaceManager.get().executeFunction(source, functionHandle, inputPage, channels, this);
}

public void validateFunctionCall(FunctionHandle functionHandle, List<?> arguments)
{
// Built-in functions don't need validation
if (functionHandle instanceof BuiltInFunctionHandle) {
return;
}

Optional<FunctionNamespaceManager<?>> functionNamespaceManager = getServingFunctionNamespaceManager(functionHandle.getCatalogSchemaName());
if (functionNamespaceManager.isPresent()) {
functionNamespaceManager.get().validateFunctionCall(functionHandle, arguments);
}
}

public WindowFunctionSupplier getWindowFunctionImplementation(FunctionHandle functionHandle)
{
return builtInTypeAndFunctionNamespaceManager.getWindowFunctionImplementation(functionHandle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,10 @@ else if (frame.getType() == GROUPS) {
FunctionHandle function = resolveFunction(sessionFunctions, transactionId, node, argumentTypes, functionAndTypeResolver);
FunctionMetadata functionMetadata = functionAndTypeResolver.getFunctionMetadata(function);

// Delegate function-specific validation to the FunctionNamespaceManager
// This allows function namespaces to perform custom validation
functionAndTypeResolver.validateFunctionCall(function, node.getArguments());

if (node.getOrderBy().isPresent()) {
for (SortItem sortItem : node.getOrderBy().get().getSortItems()) {
Type sortKeyType = process(sortItem.getSortKey(), context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,18 @@ default AggregationFunctionImplementation getAggregateFunctionImplementation(Fun
{
throw new UnsupportedOperationException("Does not support get aggregation function");
}

/**
* Validate a function call during analysis phase on the coordinator.
* This allows function namespace managers to perform custom validation logic
* such as security checks, argument validation, etc.
*
* @param functionHandle The function handle being validated
* @param arguments Raw argument expressions (not yet evaluated) - type is Object to avoid SPI module dependencies
* @throws RuntimeException if validation fails
*/
default void validateFunctionCall(FunctionHandle functionHandle, List<?> arguments)
{
// Default implementation: no validation
}
}
Loading