Skip to content

Commit 243a82c

Browse files
committed
Add support for language function engines
1 parent 41fa390 commit 243a82c

22 files changed

+810
-73
lines changed

core/trino-main/src/main/java/io/trino/execution/CreateFunctionTask.java

+36
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,27 @@
3333
import io.trino.sql.tree.Expression;
3434
import io.trino.sql.tree.FunctionSpecification;
3535
import io.trino.sql.tree.Node;
36+
import io.trino.sql.tree.NodeRef;
37+
import io.trino.sql.tree.Parameter;
38+
import io.trino.sql.tree.PropertiesCharacteristic;
39+
import io.trino.sql.tree.Property;
3640
import io.trino.sql.tree.QualifiedName;
3741

3842
import java.util.List;
43+
import java.util.Map;
3944
import java.util.Optional;
4045
import java.util.function.BiFunction;
4146

47+
import static com.google.common.collect.ImmutableList.toImmutableList;
4248
import static com.google.common.util.concurrent.Futures.immediateVoidFuture;
49+
import static io.trino.execution.ParameterExtractor.bindParameters;
4350
import static io.trino.spi.StandardErrorCode.ALREADY_EXISTS;
4451
import static io.trino.spi.StandardErrorCode.GENERIC_INTERNAL_ERROR;
4552
import static io.trino.spi.StandardErrorCode.NOT_SUPPORTED;
4653
import static io.trino.spi.StandardErrorCode.SYNTAX_ERROR;
4754
import static io.trino.sql.SqlFormatter.formatSql;
4855
import static io.trino.sql.analyzer.SemanticExceptions.semanticException;
56+
import static io.trino.sql.routine.SqlRoutineAnalyzer.getProperties;
4957
import static io.trino.sql.routine.SqlRoutineAnalyzer.isRunAsInvoker;
5058
import static java.util.Objects.requireNonNull;
5159

@@ -94,6 +102,8 @@ public ListenableFuture<Void> execute(CreateFunction statement, QueryStateMachin
94102

95103
languageFunctionManager.verifyForCreate(session, function, functionManager, accessControl);
96104

105+
function = materializeFunctionProperties(session, function, bindParameters(statement, parameters));
106+
97107
String signatureToken = languageFunctionManager.getSignatureToken(function.getParameters());
98108

99109
String sql = functionToSql(function);
@@ -121,6 +131,32 @@ public ListenableFuture<Void> execute(CreateFunction statement, QueryStateMachin
121131
return immediateVoidFuture();
122132
}
123133

134+
private FunctionSpecification materializeFunctionProperties(Session session, FunctionSpecification function, Map<NodeRef<Parameter>, Expression> parameters)
135+
{
136+
List<Property> originalProperties = getProperties(function);
137+
if (originalProperties.isEmpty()) {
138+
return function;
139+
}
140+
141+
List<Property> sqlProperties = languageFunctionManager.materializeFunctionProperties(session, function, parameters, accessControl);
142+
143+
return new FunctionSpecification(
144+
function.getLocation().orElseThrow(),
145+
function.getName(),
146+
function.getParameters(),
147+
function.getReturnsClause(),
148+
function.getRoutineCharacteristics().stream()
149+
.map(characteristic -> {
150+
if (characteristic instanceof PropertiesCharacteristic) {
151+
return new PropertiesCharacteristic(characteristic.getLocation().orElseThrow(), sqlProperties);
152+
}
153+
return characteristic;
154+
})
155+
.collect(toImmutableList()),
156+
function.getStatement(),
157+
function.getDefinition());
158+
}
159+
124160
private String functionToSql(FunctionSpecification function)
125161
{
126162
String sql = formatSql(function);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.metadata;
15+
16+
import com.google.common.collect.ImmutableMap;
17+
import io.trino.spi.type.Type;
18+
19+
import java.util.List;
20+
import java.util.Map;
21+
22+
import static java.util.Objects.requireNonNull;
23+
24+
public record LanguageFunctionDefinition(
25+
String language,
26+
Type returnType,
27+
List<Type> argumentTypes,
28+
String definition,
29+
Map<String, Object> properties)
30+
{
31+
public LanguageFunctionDefinition
32+
{
33+
requireNonNull(language, "language is null");
34+
requireNonNull(returnType, "returnType is null");
35+
requireNonNull(argumentTypes, "argumentTypes is null");
36+
requireNonNull(definition, "definition is null");
37+
properties = ImmutableMap.copyOf(requireNonNull(properties, "properties is null"));
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.metadata;
15+
16+
import io.trino.spi.function.LanguageFunctionEngine;
17+
18+
import java.util.Map;
19+
import java.util.Optional;
20+
import java.util.concurrent.ConcurrentHashMap;
21+
22+
import static java.util.Locale.ENGLISH;
23+
24+
public class LanguageFunctionEngineManager
25+
{
26+
private final Map<String, LanguageFunctionEngine> languageFunctionEngines = new ConcurrentHashMap<>();
27+
28+
public Optional<LanguageFunctionEngine> getLanguageFunctionEngine(String language)
29+
{
30+
return Optional.ofNullable(languageFunctionEngines.get(language.toUpperCase(ENGLISH)));
31+
}
32+
33+
public void addLanguageFunctionEngine(LanguageFunctionEngine engine)
34+
{
35+
if (languageFunctionEngines.putIfAbsent(engine.getLanguage().toUpperCase(ENGLISH), engine) != null) {
36+
throw new IllegalArgumentException("Language function engine for language %s is already registered".formatted(engine.getLanguage()));
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)