[NO ISSUE] Improve handling of udf parameter/return types
- user model changes: yes
- storage format changes: no
- interface changes: no
Details:
- Prohibit parameter/return type specification for inline udfs
- Prohibit parameter/return type quantifier (?) for external udfs
- Allow external udfs to refer to types from other dataverses
- Do not store type quantifiers in udf metadata
- Align names of anonymous types automatically created by
QueryTranslator for datasets and udfs
- Reserve user-defined type names starting from '$' for system use
- Add testcases
- Prohibit UdfServlet operations if cluster is not active
- Return correct path from IOManager.getWorkspacePath()
- Test framework: support multiple commands in .lib.sqlpp files
- Remove CC files when deleting old instance data in
AsterixHyracksIntegrationUtil
Change-Id: I09bdfd8c7b26750d12339034d2143a16102d1212
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/6545
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 3bd8f42..0f8a790 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -896,11 +896,9 @@
if (function == null) {
return null;
}
- IFunctionInfo finfo =
- function.isExternal()
- ? ExternalFunctionCompilerUtil
- .getExternalFunctionInfo(metadataProvider.getMetadataTxnContext(), function)
- : FunctionUtil.getFunctionInfo(signature);
+ IFunctionInfo finfo = function.isExternal()
+ ? ExternalFunctionCompilerUtil.getExternalFunctionInfo(metadataProvider, function)
+ : FunctionUtil.getFunctionInfo(signature);
AbstractFunctionCallExpression f = new ScalarFunctionCallExpression(finfo, args);
f.setSourceLocation(sourceLoc);
return f;
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UdfApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UdfApiServlet.java
index 71be106..b0da8e0 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UdfApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UdfApiServlet.java
@@ -35,6 +35,7 @@
import org.apache.asterix.app.external.ExternalLibraryUtils;
import org.apache.asterix.app.message.LoadUdfMessage;
+import org.apache.asterix.common.api.IClusterManagementWork;
import org.apache.asterix.common.dataflow.ICcApplicationContext;
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.common.exceptions.ErrorCode;
@@ -103,6 +104,12 @@
@Override
protected void post(IServletRequest request, IServletResponse response) {
+ IClusterManagementWork.ClusterState clusterState = appCtx.getClusterStateManager().getState();
+ if (clusterState != IClusterManagementWork.ClusterState.ACTIVE) {
+ response.setStatus(HttpResponseStatus.SERVICE_UNAVAILABLE);
+ return;
+ }
+
PrintWriter responseWriter = response.writer();
FullHttpRequest req = request.getHttpRequest();
Pair<String, DataverseName> resourceNames;
@@ -238,11 +245,11 @@
throws RemoteException, AlgebricksException {
Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, dataverse);
if (dv == null) {
- throw new AsterixException(ErrorCode.UNKNOWN_DATAVERSE);
+ throw new AsterixException(ErrorCode.UNKNOWN_DATAVERSE, dataverse);
}
Library library = MetadataManager.INSTANCE.getLibrary(mdTxnCtx, dataverse, libraryName);
if (library == null) {
- throw new AsterixException(ErrorCode.UNKNOWN_LIBRARY);
+ throw new AsterixException(ErrorCode.UNKNOWN_LIBRARY, libraryName);
}
List<Function> functions = MetadataManager.INSTANCE.getDataverseFunctions(mdTxnCtx, dataverse);
for (Function function : functions) {
@@ -261,6 +268,12 @@
@Override
protected void delete(IServletRequest request, IServletResponse response) {
+ IClusterManagementWork.ClusterState clusterState = appCtx.getClusterStateManager().getState();
+ if (clusterState != IClusterManagementWork.ClusterState.ACTIVE) {
+ response.setStatus(HttpResponseStatus.SERVICE_UNAVAILABLE);
+ return;
+ }
+
Pair<String, DataverseName> resourceNames;
try {
resourceNames = getResource(request.getHttpRequest());
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index 1e4e15b..12fe09b 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -172,10 +172,10 @@
import org.apache.asterix.metadata.utils.KeyFieldTypeUtil;
import org.apache.asterix.metadata.utils.MetadataConstants;
import org.apache.asterix.metadata.utils.MetadataUtil;
+import org.apache.asterix.metadata.utils.TypeUtil;
import org.apache.asterix.om.base.IAObject;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.AUnionType;
import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.types.TypeSignature;
@@ -600,7 +600,7 @@
break;
case RECORD:
itemTypeDataverseName = dataverseName;
- itemTypeName = DatasetUtil.createInlineTypeName(datasetName, false);
+ itemTypeName = TypeUtil.createDatasetInlineTypeName(datasetName, false);
itemTypeAnonymous = true;
break;
default:
@@ -624,7 +624,7 @@
break;
case RECORD:
metaItemTypeDataverseName = dataverseName;
- metaItemTypeName = DatasetUtil.createInlineTypeName(datasetName, true);
+ metaItemTypeName = TypeUtil.createDatasetInlineTypeName(datasetName, true);
metaItemTypeAnonymous = true;
break;
default:
@@ -1378,6 +1378,9 @@
if (BuiltinTypeMap.getBuiltinType(typeName) != null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
"Cannot redefine builtin type " + typeName + ".");
+ } else if (TypeUtil.isReservedInlineTypeName(typeName)) {
+ throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
+ "Reserved type name " + typeName + ".");
} else {
IAType type = translateType(dataverseName, typeName, stmtCreateType.getTypeDef(), mdTxnCtx);
MetadataManager.INSTANCE.addDatatype(mdTxnCtx, new Datatype(dataverseName, typeName, type, false));
@@ -1634,14 +1637,14 @@
// prepare to drop item and meta types if they were created as inline types
DataverseName itemTypeDataverseName = ds.getItemTypeDataverseName();
String itemTypeName = ds.getItemTypeName();
- boolean isInlineItemType = DatasetUtil.isInlineTypeName(ds, itemTypeDataverseName, itemTypeName);
+ boolean isInlineItemType = TypeUtil.isDatasetInlineTypeName(ds, itemTypeDataverseName, itemTypeName);
if (isInlineItemType) {
lockUtil.dropTypeBegin(lockManager, metadataProvider.getLocks(), itemTypeDataverseName, itemTypeName);
}
DataverseName metaTypeDataverseName = ds.getMetaItemTypeDataverseName();
String metaTypeName = ds.getMetaItemTypeName();
boolean isInlineMetaType =
- metaTypeName != null && DatasetUtil.isInlineTypeName(ds, metaTypeDataverseName, metaTypeName);
+ metaTypeName != null && TypeUtil.isDatasetInlineTypeName(ds, metaTypeDataverseName, metaTypeName);
if (isInlineMetaType) {
lockUtil.dropTypeBegin(lockManager, metadataProvider.getLocks(), metaTypeDataverseName, metaTypeName);
}
@@ -1966,56 +1969,37 @@
if (dv == null) {
throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverseName);
}
- String typeNamePrefix = createFunctionTypeNamePrefix(signature.getName(), signature.getArity());
- List<Pair<VarIdentifier, IndexedTypeExpression>> cfsArgs = cfs.getArgs();
- int argCount = cfsArgs.size();
- List<String> argNames = new ArrayList<>(argCount);
- List<IAType> argTypes = new ArrayList<>(argCount);
- List<VarIdentifier> paramVars = new ArrayList<>(argCount);
- LinkedHashSet<Pair<DataverseName, String>> dependentTypes = new LinkedHashSet<>();
- for (int i = 0; i < argCount; i++) {
- Pair<VarIdentifier, IndexedTypeExpression> argPair = cfsArgs.get(i);
- VarIdentifier argVar = argPair.getFirst();
- IndexedTypeExpression argTypeExpr = argPair.getSecond();
- IAType argType;
- if (argTypeExpr == null) {
- argType = BuiltinType.ANY;
- } else {
- Pair<DataverseName, String> depTypeName =
- FunctionUtil.getDependencyFromParameterType(argTypeExpr, dataverseName);
- if (depTypeName != null) {
- dependentTypes.add(depTypeName);
- }
- TypeSignature argTypeSignature = new TypeSignature(dataverseName, typeNamePrefix + '$' + i);
- argType = translateType(argTypeSignature, argTypeExpr, dataverseName, mdTxnCtx);
- if (argType == null) {
- String errMessage = depTypeName != null ? depTypeName.first + "." + depTypeName.second : "";
- throw new CompilationException(ErrorCode.UNKNOWN_TYPE, sourceLoc, errMessage);
- }
+ boolean isExternal = cfs.isExternal();
+
+ List<Pair<VarIdentifier, TypeExpression>> paramList = cfs.getParameters();
+ int paramCount = paramList.size();
+ List<VarIdentifier> paramVars = new ArrayList<>(paramCount);
+ List<String> paramNames = new ArrayList<>(paramCount);
+ List<TypeSignature> paramTypes = new ArrayList<>(paramCount);
+ LinkedHashSet<TypeSignature> dependentTypes = new LinkedHashSet<>();
+
+ for (int i = 0; i < paramCount; i++) {
+ Pair<VarIdentifier, TypeExpression> paramPair = paramList.get(i);
+ VarIdentifier paramName = paramPair.getFirst();
+ TypeExpression paramTypeExpr = paramPair.getSecond();
+ Pair<TypeSignature, TypeSignature> paramType = translateFunctionParameterType(signature, i,
+ paramTypeExpr, isExternal, sourceLoc, metadataProvider, mdTxnCtx);
+ paramVars.add(paramName);
+ paramNames.add(stmtRewriter.toFunctionParameterName(paramName));
+ paramTypes.add(paramType.first);
+ if (paramType.second != null) {
+ dependentTypes.add(paramType.second);
}
- paramVars.add(argVar);
- argNames.add(stmtRewriter.toFunctionParameterName(argVar));
- argTypes.add(argType);
}
- IndexedTypeExpression returnTypeExpr = cfs.getReturnType();
- IAType returnType;
- if (returnTypeExpr == null) {
- returnType = BuiltinType.ANY;
- } else {
- Pair<DataverseName, String> depTypeName =
- FunctionUtil.getDependencyFromParameterType(returnTypeExpr, dataverseName);
- if (depTypeName != null) {
- dependentTypes.add(depTypeName);
- }
- TypeSignature returnTypeSignature = new TypeSignature(dataverseName, typeNamePrefix);
- returnType = translateType(returnTypeSignature, returnTypeExpr, dataverseName, mdTxnCtx);
- if (returnType == null) {
- String errMessage = depTypeName != null ? depTypeName.first + "." + depTypeName.second : "";
- throw new CompilationException(ErrorCode.UNKNOWN_TYPE, sourceLoc, errMessage);
- }
+ TypeExpression returnTypeExpr = cfs.getReturnType();
+ Pair<TypeSignature, TypeSignature> returnType = translateFunctionParameterType(signature, -1,
+ returnTypeExpr, isExternal, sourceLoc, metadataProvider, mdTxnCtx);
+ if (returnType.second != null) {
+ dependentTypes.add(returnType.second);
}
- if (cfs.isExternal()) {
+
+ if (isExternal) {
String lang = cfs.getLang();
if (lang == null) {
throw new CompilationException(ErrorCode.COMPILATION_INCOMPATIBLE_FUNCTION_LANGUAGE, sourceLoc, "");
@@ -2036,7 +2020,7 @@
cfs.getExternalIdentifier());
List<List<Triple<DataverseName, String, String>>> dependencies =
FunctionUtil.getExternalFunctionDependencies(dependentTypes);
- Function f = new Function(signature, argNames, argTypes, returnType, body,
+ Function f = new Function(signature, paramNames, paramTypes, returnType.first, body,
FunctionKind.SCALAR.toString(), functionLang.name(), libraryName, cfs.getNullCall(),
cfs.getDeterministic(), cfs.getResources(), dependencies);
MetadataManager.INSTANCE.addFunction(mdTxnCtx, f);
@@ -2056,9 +2040,9 @@
List<List<Triple<DataverseName, String, String>>> dependencies =
FunctionUtil.getFunctionDependencies(rewriterFactory.createQueryRewriter(),
cfs.getFunctionBodyExpression(), metadataProvider, dependentTypes);
- Function function = new Function(signature, argNames, argTypes, returnType, cfs.getFunctionBody(),
- FunctionKind.SCALAR.toString(), compilationProvider.getParserFactory().getLanguage(), null,
- null, null, null, dependencies);
+ Function function = new Function(signature, paramNames, paramTypes, returnType.first,
+ cfs.getFunctionBody(), FunctionKind.SCALAR.toString(),
+ compilationProvider.getParserFactory().getLanguage(), null, null, null, null, dependencies);
MetadataManager.INSTANCE.addFunction(mdTxnCtx, function);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Installed function: " + signature);
@@ -2071,19 +2055,59 @@
}
}
- private static IAType translateType(TypeSignature typeSignature, IndexedTypeExpression typeExpr,
- DataverseName defaultDataverse, MetadataTransactionContext mdTxnCtx) throws AlgebricksException {
- Map<TypeSignature, IAType> typeMap = TypeTranslator.computeTypes(typeSignature.getDataverseName(),
- typeSignature.getName(), typeExpr.getType(), defaultDataverse, mdTxnCtx);
- IAType type = typeMap.get(typeSignature);
- if (type != null && typeExpr.isUnknownable()) {
- type = AUnionType.createUnknownableType(type);
+ private Pair<TypeSignature, TypeSignature> translateFunctionParameterType(FunctionSignature functionSignature,
+ int paramIdx, TypeExpression paramTypeExpr, boolean isExternalFunction, SourceLocation sourceLoc,
+ MetadataProvider metadataProvider, MetadataTransactionContext mdTxnCtx) throws AlgebricksException {
+ if (paramTypeExpr == null) {
+ return new Pair<>(TypeUtil.ANY_TYPE_SIGNATURE, null);
}
- return type;
- }
- private static String createFunctionTypeNamePrefix(String name, int arity) {
- return "fn$" + name + "$" + arity;
+ if (!isExternalFunction) {
+ // grammar doesn't allow parameter types for inline functions
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc);
+ }
+
+ TypeSignature resultType, dependentType;
+
+ switch (paramTypeExpr.getTypeKind()) {
+ case TYPEREFERENCE:
+ TypeReferenceExpression paramTypeRefExpr = (TypeReferenceExpression) paramTypeExpr;
+ String paramTypeName = paramTypeRefExpr.getIdent().second.getValue();
+ BuiltinType builtinType = BuiltinTypeMap.getBuiltinType(paramTypeName);
+ if (builtinType != null) {
+ // built-in type
+ resultType = new TypeSignature(builtinType);
+ dependentType = null;
+ } else {
+ // user-defined type
+ DataverseName paramTypeDataverseName = paramTypeRefExpr.getIdent().first;
+ if (paramTypeDataverseName == null) {
+ paramTypeDataverseName = functionSignature.getDataverseName();
+ }
+ IAType paramType = metadataProvider.findType(paramTypeDataverseName, paramTypeName);
+ if (paramType == null) {
+ throw new CompilationException(ErrorCode.UNKNOWN_TYPE, sourceLoc, paramTypeName);
+ }
+ resultType = dependentType = new TypeSignature(paramTypeDataverseName, paramTypeName);
+ }
+ break;
+ case ORDEREDLIST:
+ case UNORDEREDLIST:
+ DataverseName paramTypeDataverseName = functionSignature.getDataverseName();
+ paramTypeName = TypeUtil.createFunctionParameterTypeName(functionSignature.getName(),
+ functionSignature.getArity(), paramIdx);
+ IAType paramType = translateType(paramTypeDataverseName, paramTypeName, paramTypeExpr, mdTxnCtx);
+ MetadataManager.INSTANCE.addDatatype(mdTxnCtx,
+ new Datatype(paramTypeDataverseName, paramTypeName, paramType, true));
+ resultType = new TypeSignature(paramTypeDataverseName, paramTypeName);
+ dependentType = FunctionUtil.getTypeDependencyFromFunctionParameter(paramTypeExpr,
+ functionSignature.getDataverseName());
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc);
+ }
+
+ return new Pair<>(resultType, dependentType);
}
protected void handleCreateAdapterStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
index 1079fb8..117fb63 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
@@ -135,6 +135,7 @@
if (deleteOldInstanceData) {
deleteTransactionLogs();
removeTestStorageFiles();
+ deleteCCFiles();
}
final List<NodeControllerService> nodeControllers = new ArrayList<>();
for (String nodeId : nodeNames) {
@@ -306,6 +307,7 @@
if (deleteOldInstanceData) {
deleteTransactionLogs();
removeTestStorageFiles();
+ deleteCCFiles();
}
}
@@ -342,6 +344,12 @@
}
}
+ private void deleteCCFiles() {
+ if (cc != null) {
+ FileUtils.deleteQuietly(new File(cc.getCCConfig().getRootDir()));
+ }
+ }
+
protected void run(boolean cleanupOnStart, boolean cleanupOnShutdown, String loadExternalLibs, String confFile)
throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread() {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index 4275aa6..2acb391 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -1196,36 +1196,37 @@
// <library-directory>
// TODO: make this case work well with entity names containing spaces by
// looking for \"
- lines = statement.split("\n");
- String lastLine = lines[lines.length - 1];
- String[] command = lastLine.trim().split(" ");
- if (command.length < 2) {
- throw new Exception("invalid library format");
- }
- String dataverse = command[1];
- String library = command[2];
- String username = command[3];
- String pw = command[4];
- switch (command[0]) {
- case "install":
- if (command.length != 6) {
+ lines = stripAllComments(statement).trim().split("\n");
+ for (String line : lines) {
+ String[] command = line.trim().split(" ");
+ if (command.length < 2) {
+ throw new Exception("invalid library command: " + line);
+ }
+ String dataverse = command[1];
+ String library = command[2];
+ String username = command[3];
+ String pw = command[4];
+ switch (command[0]) {
+ case "install":
+ if (command.length != 6) {
+ throw new Exception("invalid library format");
+ }
+ String libPath = command[5];
+ librarian.install(dataverse, library, libPath, new Pair<>(username, pw));
+ break;
+ case "uninstall":
+ if (command.length != 5) {
+ throw new Exception("invalid library format");
+ }
+ librarian.uninstall(dataverse, library, new Pair<>(username, pw));
+ break;
+ default:
throw new Exception("invalid library format");
- }
- String libPath = command[5];
- librarian.install(dataverse, library, libPath, new Pair(username, pw));
- break;
- case "uninstall":
- if (command.length != 5) {
- throw new Exception("invalid library format");
- }
- librarian.uninstall(dataverse, library, new Pair(username, pw));
- break;
- default:
- throw new Exception("invalid library format");
+ }
}
break;
case "node":
- command = stripJavaComments(statement).trim().split(" ");
+ String[] command = stripJavaComments(statement).trim().split(" ");
String commandType = command[0];
String nodeId = command[1];
switch (commandType) {
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/bad-type-ddl/bad-type-ddl.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/bad-type-ddl/bad-type-ddl.1.ddl.sqlpp
new file mode 100644
index 0000000..42927bd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/bad-type-ddl/bad-type-ddl.1.ddl.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description : Reserved type name
+ * Expected Res : Error
+ */
+
+drop dataverse experiments if exists;
+create dataverse experiments;
+use experiments;
+
+create type `$x` as {
+ c : string
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.0.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.0.ddl.sqlpp
index 5a5bbec..7237fff 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.0.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.0.ddl.sqlpp
@@ -21,6 +21,15 @@
USE externallibtest;
create type CountryCapitalType if not exists as closed {
-country: string,
-capital: string
+ country: string,
+ capital: string
+};
+
+DROP DATAVERSE externallibtest2 if exists;
+CREATE DATAVERSE externallibtest2;
+USE externallibtest2;
+
+create type CountryCapitalType2 if not exists as open {
+ country: string,
+ capital: string
};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.1.lib.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.1.lib.sqlpp
index 3dc6eb6..b4197f1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.1.lib.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.1.lib.sqlpp
@@ -17,3 +17,4 @@
* under the License.
*/
install externallibtest testlib admin admin target/data/externallib/asterix-external-data-testlib.zip
+install externallibtest2 testlib2 admin admin target/data/externallib/asterix-external-data-testlib.zip
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.2.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.2.ddl.sqlpp
index 2826b9e..bcb86ac 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.2.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.2.ddl.sqlpp
@@ -33,22 +33,22 @@
returns CountryCapitalType
language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
-create function myfn005(a:string?, b:[bigint]?, c:CountryCapitalType?, d:[CountryCapitalType]?)
- returns string?
+create function myfn005(a:smallint, b:[bigint], c:CountryCapitalType, d:[CountryCapitalType])
+ returns string
language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
create function myfn006(a [string])
returns [string]
language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
-create function myfn007(a {{string}}?)
- returns {{string}}?
+create function myfn007(a {{string}})
+ returns {{string}}
language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
create function myfn008(a [CountryCapitalType])
returns [CountryCapitalType]
language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
-create function myfn009(a {{CountryCapitalType}}?)
- returns {{CountryCapitalType}}?
- language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
+create function externallibtest2.myfn009(a externallibtest.CountryCapitalType)
+ returns externallibtest.CountryCapitalType
+ language java as "testlib2","org.apache.asterix.external.library.CapitalFinderFactory";
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.3.query.sqlpp
index b099f5f..fbdfd9f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.3.query.sqlpp
@@ -19,9 +19,9 @@
SELECT object_remove(fn, "Timestamp") as fn
FROM Metadata.`Function` fn
-WHERE fn.DataverseName = "externallibtest"
+WHERE fn.DataverseName like "externallibtest%"
UNION ALL
SELECT object_remove(dt, "Timestamp") as dt
FROM Metadata.`Datatype` dt
-WHERE dt.DataverseName = "externallibtest"
+WHERE dt.DataverseName like "externallibtest%"
ORDER BY dt.DatatypeName, fn.Name;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.4.ddl.sqlpp
index cb57494..2fc3b7e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.4.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.4.ddl.sqlpp
@@ -16,4 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
+DROP DATAVERSE externallibtest2;
DROP DATAVERSE externallibtest;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/bad-function-ddl-11/bad-function-ddl-11.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/bad-function-ddl-11/bad-function-ddl-11.1.ddl.sqlpp
new file mode 100644
index 0000000..eaddc21
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/bad-function-ddl-11/bad-function-ddl-11.1.ddl.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description : Parameter type definition is prohibited for inline functions
+ * Expected Res : Error
+ */
+
+drop dataverse experiments if exists;
+create dataverse experiments;
+use experiments;
+
+create function myfn001(a:string) {
+ a
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/bad-function-ddl-11/bad-function-ddl-11.2.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/bad-function-ddl-11/bad-function-ddl-11.2.ddl.sqlpp
new file mode 100644
index 0000000..9b2c6f0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/bad-function-ddl-11/bad-function-ddl-11.2.ddl.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description : Return type definition is prohibited for inline functions
+ * Expected Res : Error
+ */
+
+drop dataverse experiments if exists;
+create dataverse experiments;
+use experiments;
+
+create function myfn002(a) returns string {
+ a
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.1.ddl.sqlpp
index 9f268d1..8392e6c3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.1.ddl.sqlpp
@@ -21,11 +21,6 @@
use test;
-create type MyType1 as {
- `id`: int,
- `value`: string
-};
-
create function myfn001() {
42
};
@@ -34,30 +29,6 @@
a
};
-create function myfn003(a:string, b:[bigint], c:{{boolean}}) returns string {
- a
-};
-
-create function myfn004(a:MyType1, b:[MyType1]) returns MyType1 {
- a
-};
-
-create function myfn005(a:string?, b:[bigint]?, c:MyType1?, d:[MyType1]?) returns string? {
- a
-};
-
-create function myfn006(a [string]) returns [string] {
- a
-};
-
-create function myfn007(a {{string}}?) returns {{string}}? {
- a
-};
-
-create function myfn008(a [MyType1]) returns [MyType1] {
- a
-};
-
-create function myfn009(a {{MyType1}}?) returns {{MyType1}}? {
- a
-};
+create function myfn003(a, b) {
+ a + b
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm
index 67f81b2..913eab7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm
@@ -1,23 +1,22 @@
{ "fn": { "DataverseName": "externallibtest", "Name": "myfn001", "Arity": "0", "Params": [ ], "ReturnType": "any", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
{ "fn": { "DataverseName": "externallibtest", "Name": "myfn002", "Arity": "1", "Params": [ "a" ], "ReturnType": "any", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "any" } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn003", "Arity": "3", "Params": [ "a", "b", "c" ], "ReturnType": "string", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "string", "IsNullable": false }, { "Type": "fn$myfn003$3$1", "IsNullable": false }, { "Type": "fn$myfn003$3$2", "IsNullable": false } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn004", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "CountryCapitalType", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "CountryCapitalType", "IsNullable": false }, { "Type": "fn$myfn004$2$1", "IsNullable": false } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn005", "Arity": "4", "Params": [ "a", "b", "c", "d" ], "ReturnType": "string", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ReturnTypeIsNullable": true, "ParamTypes": [ { "Type": "string", "IsNullable": true }, { "Type": "fn$myfn005$4$1", "IsNullable": true }, { "Type": "CountryCapitalType", "IsNullable": true }, { "Type": "fn$myfn005$4$3", "IsNullable": true } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn006", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn006$1", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "fn$myfn006$1$0", "IsNullable": false } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn007", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn007$1", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ReturnTypeIsNullable": true, "ParamTypes": [ { "Type": "fn$myfn007$1$0", "IsNullable": true } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn008", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn008$1", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "fn$myfn008$1$0", "IsNullable": false } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn009", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn009$1", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ReturnTypeIsNullable": true, "ParamTypes": [ { "Type": "fn$myfn009$1$0", "IsNullable": true } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn003", "Arity": "3", "Params": [ "a", "b", "c" ], "ReturnType": "string", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "string" }, { "Type": "$f$t$myfn003$3$1" }, { "Type": "$f$t$myfn003$3$2" } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn004", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "CountryCapitalType", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ParamTypes": [ { "Type": "CountryCapitalType" }, { "Type": "$f$t$myfn004$2$1" } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn005", "Arity": "4", "Params": [ "a", "b", "c", "d" ], "ReturnType": "string", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ParamTypes": [ { "Type": "int16" }, { "Type": "$f$t$myfn005$4$1" }, { "Type": "CountryCapitalType" }, { "Type": "$f$t$myfn005$4$3" } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn006", "Arity": "1", "Params": [ "a" ], "ReturnType": "$f$t$myfn006$1", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "$f$t$myfn006$1$0" } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn007", "Arity": "1", "Params": [ "a" ], "ReturnType": "$f$t$myfn007$1", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "$f$t$myfn007$1$0" } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn008", "Arity": "1", "Params": [ "a" ], "ReturnType": "$f$t$myfn008$1", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ParamTypes": [ { "Type": "$f$t$myfn008$1$0" } ], "Library": "testlib", "NullCall": false, "Deterministic": false } }
+{ "fn": { "DataverseName": "externallibtest2", "Name": "myfn009", "Arity": "1", "Params": [ "a" ], "ReturnType": "CountryCapitalType", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ReturnTypeDataverseName": "externallibtest", "ParamTypes": [ { "Type": "CountryCapitalType", "DataverseName": "externallibtest" } ], "Library": "testlib2", "NullCall": false, "Deterministic": false } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn003$3$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "int64" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn003$3$2", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "boolean" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn004$2$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn005$4$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "int64" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn005$4$3", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn006$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "string" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn006$1$0", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "string" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn007$1", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "string" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn007$1$0", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "string" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn008$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "$f$t$myfn008$1$0", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "CountryCapitalType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "Record": { "IsOpen": false, "Fields": [ { "FieldName": "country", "FieldType": "string", "IsNullable": false, "IsMissable": false }, { "FieldName": "capital", "FieldType": "string", "IsNullable": false, "IsMissable": false } ] } } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn003$3$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "int64" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn003$3$2", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "boolean" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn004$2$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn005$4$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "int64" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn005$4$3", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn006$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "string" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn006$1$0", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "string" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn007$1", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "string" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn007$1$0", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "string" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn008$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn008$1$0", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "CountryCapitalType" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn009$1", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "CountryCapitalType" } } }
-{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "fn$myfn009$1$0", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "CountryCapitalType" } } }
+{ "dt": { "DataverseName": "externallibtest2", "DatatypeName": "CountryCapitalType2", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "country", "FieldType": "string", "IsNullable": false, "IsMissable": false }, { "FieldName": "capital", "FieldType": "string", "IsNullable": false, "IsMissable": false } ] } } } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf32_metadata/udf32_metadata.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf32_metadata/udf32_metadata.2.adm
index c78c3d4..07f3289 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf32_metadata/udf32_metadata.2.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf32_metadata/udf32_metadata.2.adm
@@ -1,23 +1,3 @@
{ "fn": { "DataverseName": "test", "Name": "myfn001", "Arity": "0", "Params": [ ], "ReturnType": "any", "Definition": "42", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ ] } }
{ "fn": { "DataverseName": "test", "Name": "myfn002", "Arity": "1", "Params": [ "a" ], "ReturnType": "any", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "any" } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn003", "Arity": "3", "Params": [ "a", "b", "c" ], "ReturnType": "string", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "string", "IsNullable": false }, { "Type": "fn$myfn003$3$1", "IsNullable": false }, { "Type": "fn$myfn003$3$2", "IsNullable": false } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn004", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "MyType1", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "test", "MyType1" ] ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "MyType1", "IsNullable": false }, { "Type": "fn$myfn004$2$1", "IsNullable": false } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn005", "Arity": "4", "Params": [ "a", "b", "c", "d" ], "ReturnType": "string", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "test", "MyType1" ] ] ], "ReturnTypeIsNullable": true, "ParamTypes": [ { "Type": "string", "IsNullable": true }, { "Type": "fn$myfn005$4$1", "IsNullable": true }, { "Type": "MyType1", "IsNullable": true }, { "Type": "fn$myfn005$4$3", "IsNullable": true } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn006", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn006$1", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "fn$myfn006$1$0", "IsNullable": false } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn007", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn007$1", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ReturnTypeIsNullable": true, "ParamTypes": [ { "Type": "fn$myfn007$1$0", "IsNullable": true } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn008", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn008$1", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "test", "MyType1" ] ] ], "ReturnTypeIsNullable": false, "ParamTypes": [ { "Type": "fn$myfn008$1$0", "IsNullable": false } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn009", "Arity": "1", "Params": [ "a" ], "ReturnType": "fn$myfn009$1", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "test", "MyType1" ] ] ], "ReturnTypeIsNullable": true, "ParamTypes": [ { "Type": "fn$myfn009$1$0", "IsNullable": true } ] } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "MyType1", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "id", "FieldType": "int64", "IsNullable": false, "IsMissable": false }, { "FieldName": "value", "FieldType": "string", "IsNullable": false, "IsMissable": false } ] } } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn003$3$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "int64" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn003$3$2", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "boolean" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn004$2$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "MyType1" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn005$4$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "int64" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn005$4$3", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "MyType1" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn006$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "string" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn006$1$0", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "string" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn007$1", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "string" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn007$1$0", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "string" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn008$1", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "MyType1" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn008$1$0", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "MyType1" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn009$1", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "MyType1" } } }
-{ "dt": { "DataverseName": "test", "DatatypeName": "fn$myfn009$1$0", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "UnorderedList": "MyType1" } } }
+{ "fn": { "DataverseName": "test", "Name": "myfn003", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "any", "Definition": "a + b", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "any" }, { "Type": "any" } ] } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index abee116..deb8503 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -3968,6 +3968,12 @@
</compilation-unit>
</test-case>
<test-case FilePath="ddl">
+ <compilation-unit name="bad-type-ddl">
+ <output-dir compare="Text">none</output-dir>
+ <expected-error>ASX1079: Compilation error: Reserved type name $x</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="ddl">
<compilation-unit name="create-dataset-inline-type-1">
<output-dir compare="Text">create-dataset-inline-type-1</output-dir>
</compilation-unit>
@@ -11714,6 +11720,13 @@
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
+ <compilation-unit name="bad-function-ddl-11">
+ <output-dir compare="Text">bad-function-ddl-11</output-dir>
+ <expected-error>ASX1001: Syntax error: Unexpected type declaration for parameter a in function myfn001</expected-error>
+ <expected-error>ASX1001: Syntax error: Unexpected return type declaration for function myfn002</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="user-defined-functions">
<compilation-unit name="check-dependencies-1">
<output-dir compare="Text">check-dependencies-1</output-dir>
</compilation-unit>
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java
index 9e1461e..b09752e 100755
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalLibraryManager.java
@@ -55,7 +55,7 @@
}
private static final Logger LOGGER = LogManager.getLogger();
- private final Map<Pair<DataverseName, String>, ILibrary> libraries = Collections.synchronizedMap(new HashMap());
+ private final Map<Pair<DataverseName, String>, ILibrary> libraries = Collections.synchronizedMap(new HashMap<>());
private final IPersistedResourceRegistry reg;
public ExternalLibraryManager(File appDir, IPersistedResourceRegistry reg) {
@@ -86,13 +86,13 @@
@Override
public void deregister(DataverseName dataverseName, String libraryName) {
Pair<DataverseName, String> key = getKey(dataverseName, libraryName);
- ILibrary cl = libraries.get(key);
+ ILibrary cl = libraries.remove(key);
if (cl != null) {
cl.close();
- libraries.remove(key);
}
}
+ @Override
public void setUpDeployedLibrary(String libraryPath) throws IOException, AsterixException {
// get the installed library dirs
String[] parts = libraryPath.split(File.separator);
diff --git a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
index 0a1d485..b9a489d 100644
--- a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
+++ b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
@@ -742,7 +742,7 @@
Token beginPos;
Token endPos;
FunctionName fctName = null;
- List<Pair<VarIdentifier,IndexedTypeExpression>> bodge = new ArrayList<Pair<VarIdentifier,IndexedTypeExpression>>();
+ List<Pair<VarIdentifier,TypeExpression>> bodge = new ArrayList<Pair<VarIdentifier,TypeExpression>>();
createNewScope();
}
{
@@ -762,9 +762,9 @@
getCurrentScope().addFunctionDescriptor(signature, false);
removeCurrentScope();
for(VarIdentifier v: paramList){
- bodge.add(new Pair<VarIdentifier,IndexedTypeExpression>(v,null));
+ bodge.add(new Pair<VarIdentifier,TypeExpression>(v,null));
}
- return new CreateFunctionStatement(signature, bodge, null, functionBody, functionBodyExpr, ifNotExists);
+ return new CreateFunctionStatement(signature, bodge, functionBody, functionBodyExpr, ifNotExists);
}
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/parser/FunctionParser.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/parser/FunctionParser.java
index e37868c..fec4f50 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/parser/FunctionParser.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/parser/FunctionParser.java
@@ -46,6 +46,6 @@
function.getLanguage());
}
IParser parser = parserFactory.createParser(new StringReader(function.getFunctionBody()));
- return parser.parseFunctionBody(function.getSignature(), function.getArgNames());
+ return parser.parseFunctionBody(function.getSignature(), function.getParameterNames());
}
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java
index 72962fa..082665f 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java
@@ -27,8 +27,8 @@
import org.apache.asterix.lang.common.base.AbstractStatement;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.lang.common.expression.IndexedTypeExpression;
import org.apache.asterix.lang.common.expression.RecordConstructor;
+import org.apache.asterix.lang.common.expression.TypeExpression;
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.lang.common.util.ConfigurationUtil;
import org.apache.asterix.lang.common.util.ExpressionUtils;
@@ -42,8 +42,8 @@
private final String functionBody;
private final Expression functionBodyExpression;
private final boolean ifNotExists;
- private final List<Pair<VarIdentifier, IndexedTypeExpression>> args;
- private final IndexedTypeExpression returnType;
+ private final List<Pair<VarIdentifier, TypeExpression>> paramList;
+ private final TypeExpression returnType;
private final String lang;
private final String libName;
@@ -52,15 +52,14 @@
private final Boolean nullCall;
private final AdmObjectNode resources;
- public CreateFunctionStatement(FunctionSignature signature,
- List<Pair<VarIdentifier, IndexedTypeExpression>> parameterList, IndexedTypeExpression returnType,
+ public CreateFunctionStatement(FunctionSignature signature, List<Pair<VarIdentifier, TypeExpression>> paramList,
String functionBody, Expression functionBodyExpression, boolean ifNotExists) {
this.signature = signature;
this.functionBody = functionBody;
this.functionBodyExpression = functionBodyExpression;
this.ifNotExists = ifNotExists;
- this.args = parameterList;
- this.returnType = returnType;
+ this.paramList = requireNullTypes(paramList);
+ this.returnType = null; // return type specification is not allowed for inline functions
this.lang = null;
this.libName = null;
this.externalIdentifier = null;
@@ -69,13 +68,13 @@
this.resources = null;
}
- public CreateFunctionStatement(FunctionSignature signature,
- List<Pair<VarIdentifier, IndexedTypeExpression>> parameterList, IndexedTypeExpression returnType,
- boolean deterministic, boolean nullCall, String lang, String libName, List<String> externalIdentifier,
- RecordConstructor resources, boolean ifNotExists) throws CompilationException {
+ public CreateFunctionStatement(FunctionSignature signature, List<Pair<VarIdentifier, TypeExpression>> paramList,
+ TypeExpression returnType, boolean deterministic, boolean nullCall, String lang, String libName,
+ List<String> externalIdentifier, RecordConstructor resources, boolean ifNotExists)
+ throws CompilationException {
this.signature = signature;
this.ifNotExists = ifNotExists;
- this.args = parameterList;
+ this.paramList = paramList;
this.returnType = returnType;
this.deterministic = deterministic;
this.nullCall = nullCall;
@@ -108,11 +107,11 @@
return functionBodyExpression;
}
- public List<Pair<VarIdentifier, IndexedTypeExpression>> getArgs() {
- return args;
+ public List<Pair<VarIdentifier, TypeExpression>> getParameters() {
+ return paramList;
}
- public IndexedTypeExpression getReturnType() {
+ public TypeExpression getReturnType() {
return returnType;
}
@@ -153,4 +152,14 @@
public byte getCategory() {
return Category.DDL;
}
+
+ private static List<Pair<VarIdentifier, TypeExpression>> requireNullTypes(
+ List<Pair<VarIdentifier, TypeExpression>> paramList) {
+ for (Pair<VarIdentifier, TypeExpression> p : paramList) {
+ if (p.second != null) {
+ throw new IllegalArgumentException(String.valueOf(p.second));
+ }
+ }
+ return paramList;
+ }
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
index 0c16f47..643d2a5 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
@@ -19,10 +19,9 @@
package org.apache.asterix.lang.common.util;
-import static org.apache.asterix.common.functions.FunctionConstants.ASTERIX_DV;
-
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -35,7 +34,6 @@
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.expression.IndexedTypeExpression;
import org.apache.asterix.lang.common.expression.OrderedListTypeDefinition;
import org.apache.asterix.lang.common.expression.TypeExpression;
import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
@@ -48,6 +46,8 @@
import org.apache.asterix.metadata.entities.BuiltinTypeMap;
import org.apache.asterix.metadata.entities.Function;
import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.TypeSignature;
import org.apache.asterix.om.utils.ConstantExpressionUtil;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -85,32 +85,30 @@
return fi;
}
- public static Pair<DataverseName, String> getDependencyFromParameterType(IndexedTypeExpression parameterType,
- DataverseName defaultDataverse) {
- Pair<DataverseName, String> typeName =
- FunctionUtil.extractNestedTypeName(parameterType.getType(), defaultDataverse);
- return typeName == null || ASTERIX_DV.equals(typeName.getFirst()) ? null : typeName;
- }
-
- private static Pair<DataverseName, String> extractNestedTypeName(TypeExpression typeExpr,
+ public static TypeSignature getTypeDependencyFromFunctionParameter(TypeExpression typeExpr,
DataverseName defaultDataverse) {
switch (typeExpr.getTypeKind()) {
case ORDEREDLIST:
- return extractNestedTypeName(((OrderedListTypeDefinition) typeExpr).getItemTypeExpression(),
- defaultDataverse);
+ return getTypeDependencyFromFunctionParameter(
+ ((OrderedListTypeDefinition) typeExpr).getItemTypeExpression(), defaultDataverse);
case UNORDEREDLIST:
- return extractNestedTypeName(((UnorderedListTypeDefinition) typeExpr).getItemTypeExpression(),
- defaultDataverse);
- case RECORD:
- break;
+ return getTypeDependencyFromFunctionParameter(
+ ((UnorderedListTypeDefinition) typeExpr).getItemTypeExpression(), defaultDataverse);
case TYPEREFERENCE:
TypeReferenceExpression typeRef = ((TypeReferenceExpression) typeExpr);
String typeName = typeRef.getIdent().getSecond().toString();
- DataverseName typeDv = BuiltinTypeMap.getBuiltinType(typeName) != null ? ASTERIX_DV
- : typeRef.getIdent().getFirst() != null ? typeRef.getIdent().getFirst() : defaultDataverse;
- return new Pair<>(typeDv, typeName);
+ BuiltinType builtinType = BuiltinTypeMap.getBuiltinType(typeName);
+ if (builtinType != null) {
+ return null;
+ }
+ DataverseName typeDataverseName =
+ typeRef.getIdent().getFirst() != null ? typeRef.getIdent().getFirst() : defaultDataverse;
+ return new TypeSignature(typeDataverseName, typeName);
+ case RECORD:
+ throw new IllegalArgumentException();
+ default:
+ throw new IllegalStateException();
}
- return null;
}
@FunctionalInterface
@@ -218,13 +216,13 @@
}
public static List<List<Triple<DataverseName, String, String>>> getFunctionDependencies(IQueryRewriter rewriter,
- Expression expression, MetadataProvider metadataProvider, Collection<Pair<DataverseName, String>> argTypes)
+ Expression expression, MetadataProvider metadataProvider, Collection<TypeSignature> dependentTypes)
throws CompilationException {
Set<CallExpr> functionCalls = rewriter.getFunctionCalls(expression);
//Get the List of used functions and used datasets
List<Triple<DataverseName, String, String>> datasourceDependencies = new ArrayList<>();
List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
- List<Triple<DataverseName, String, String>> typeDependencies = new ArrayList<>();
+ List<Triple<DataverseName, String, String>> typeDependencies = new ArrayList<>(dependentTypes.size());
for (CallExpr functionCall : functionCalls) {
FunctionSignature signature = functionCall.getFunctionSignature();
if (isBuiltinDatasetFunction(signature)) {
@@ -237,8 +235,8 @@
Integer.toString(signature.getArity())));
}
}
- for (Pair<DataverseName, String> t : argTypes) {
- typeDependencies.add(new Triple<>(t.getFirst(), t.getSecond(), null));
+ for (TypeSignature t : dependentTypes) {
+ typeDependencies.add(new Triple<>(t.getDataverseName(), t.getName(), null));
}
List<List<Triple<DataverseName, String, String>>> dependencies = new ArrayList<>(3);
dependencies.add(datasourceDependencies);
@@ -248,12 +246,12 @@
}
public static List<List<Triple<DataverseName, String, String>>> getExternalFunctionDependencies(
- Collection<Pair<DataverseName, String>> argTypes) {
- List<Triple<DataverseName, String, String>> datasourceDependencies = new ArrayList<>();
- List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
- List<Triple<DataverseName, String, String>> typeDependencies = new ArrayList<>();
- for (Pair<DataverseName, String> t : argTypes) {
- typeDependencies.add(new Triple<>(t.getFirst(), t.getSecond(), null));
+ Collection<TypeSignature> dependentTypes) {
+ List<Triple<DataverseName, String, String>> datasourceDependencies = Collections.emptyList();
+ List<Triple<DataverseName, String, String>> functionDependencies = Collections.emptyList();
+ List<Triple<DataverseName, String, String>> typeDependencies = new ArrayList<>(dependentTypes.size());
+ for (TypeSignature t : dependentTypes) {
+ typeDependencies.add(new Triple<>(t.getDataverseName(), t.getName(), null));
}
List<List<Triple<DataverseName, String, String>>> dependencies = new ArrayList<>(3);
dependencies.add(datasourceDependencies);
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
index 1de5dcf..47e934e 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
@@ -25,7 +25,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
@@ -796,8 +795,8 @@
out.print(this.generateFullName(cfs.getFunctionSignature().getDataverseName(),
cfs.getFunctionSignature().getName()));
out.print("(");
- printDelimitedStrings(cfs.getArgs().stream().map(v -> v.getFirst().getValue()).collect(Collectors.toList()),
- COMMA);
+ printDelimitedStrings(
+ cfs.getParameters().stream().map(v -> v.getFirst().getValue()).collect(Collectors.toList()), COMMA);
out.println(") {");
out.println(cfs.getFunctionBody());
out.println("}" + SEMICOLON);
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 7105a42..6f756c7 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -546,6 +546,21 @@
warningCollector.warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.UNEXPECTED_HINT, actualHint, expectedHints));
}
}
+
+ private void ensureNoTypeDeclsInFunction(String fnName, List<Pair<VarIdentifier, TypeExpression>> paramList,
+ TypeExpression returnType, Token startToken) throws SqlppParseException {
+ for (Pair<VarIdentifier, TypeExpression> p : paramList) {
+ if (p.second != null) {
+ String paramName = SqlppVariableUtil.toUserDefinedName(p.first.getValue());
+ throw new SqlppParseException(getSourceLocation(startToken),
+ "Unexpected type declaration for parameter " + paramName + " in function " + fnName);
+ }
+ }
+ if (returnType != null) {
+ throw new SqlppParseException(getSourceLocation(startToken),
+ "Unexpected return type declaration for function " + fnName);
+ }
+ }
}
PARSER_END(SQLPPParser)
@@ -1144,14 +1159,14 @@
Token endPos;
FunctionName fctName = null;
DataverseName currentDataverse = defaultDataverse;
- IndexedTypeExpression returnType = null;
+ TypeExpression returnType = null;
boolean deterministic = false;
boolean nullCall = false;
String lang = null;
String libName ="";
String externalIdent = "";
List<String> externalIdentList = null;
- List<Pair<VarIdentifier,IndexedTypeExpression>> args = null;
+ List<Pair<VarIdentifier,TypeExpression>> params = null;
RecordConstructor resources = null;
}
{
@@ -1160,7 +1175,7 @@
defaultDataverse = fctName.dataverse;
}
ifNotExists = IfNotExists()
- args = FunctionParameters()
+ params = FunctionParameters()
returnType = FunctionReturnType()
(
(
@@ -1173,11 +1188,12 @@
<RIGHTBRACE>{
endPos = token;
functionBody = extractFragment(beginPos.beginLine, beginPos.beginColumn, endPos.beginLine, endPos.beginColumn);
- signature = new FunctionSignature(fctName.dataverse, fctName.function, args.size());
+ signature = new FunctionSignature(fctName.dataverse, fctName.function, params.size());
getCurrentScope().addFunctionDescriptor(signature, false);
removeCurrentScope();
defaultDataverse = currentDataverse;
- CreateFunctionStatement stmt = new CreateFunctionStatement(signature, args, returnType, functionBody, functionBodyExpr, ifNotExists);
+ ensureNoTypeDeclsInFunction(fctName.function, params, returnType, startStmtToken);
+ CreateFunctionStatement stmt = new CreateFunctionStatement(signature, params, functionBody, functionBodyExpr, ifNotExists);
return addSourceLocation(stmt, startStmtToken);
}
)
@@ -1195,11 +1211,12 @@
{
endPos = token;
functionBody = extractFragment(beginPos.endLine, beginPos.beginColumn+1, endPos.endLine, endPos.endColumn+1);
- signature = new FunctionSignature(fctName.dataverse, fctName.function, args.size());
+ signature = new FunctionSignature(fctName.dataverse, fctName.function, params.size());
getCurrentScope().addFunctionDescriptor(signature, false);
removeCurrentScope();
defaultDataverse = currentDataverse;
- CreateFunctionStatement stmt = new CreateFunctionStatement(signature, args, returnType, functionBody, functionBodyExpr, ifNotExists);
+ ensureNoTypeDeclsInFunction(fctName.function, params, returnType, startStmtToken);
+ CreateFunctionStatement stmt = new CreateFunctionStatement(signature, params, functionBody, functionBodyExpr, ifNotExists);
return addSourceLocation(stmt, startStmtToken);
}
)
@@ -1213,12 +1230,12 @@
( <COMMA> externalIdent = ConstantString() { externalIdentList.add(externalIdent); } )+
(<WITH> resources = RecordConstructor())?
{
- signature = new FunctionSignature(fctName.dataverse, fctName.function, args.size());
+ signature = new FunctionSignature(fctName.dataverse, fctName.function, params.size());
defaultDataverse = currentDataverse;
CreateFunctionStatement stmt = null;
try{
stmt =
- new CreateFunctionStatement(signature, args, returnType, deterministic, nullCall,
+ new CreateFunctionStatement(signature, params, returnType, deterministic, nullCall,
lang, libName, externalIdentList, resources, ifNotExists);
} catch (AlgebricksException e) {
throw new SqlppParseException(getSourceLocation(startStmtToken), e.getMessage());
@@ -1230,9 +1247,9 @@
)
}
-List<Pair<VarIdentifier,IndexedTypeExpression>> FunctionParameters() :
+List<Pair<VarIdentifier,TypeExpression>> FunctionParameters() :
{
- List<Pair<VarIdentifier,IndexedTypeExpression>> paramList = Collections.<Pair<VarIdentifier,IndexedTypeExpression>>emptyList();
+ List<Pair<VarIdentifier,TypeExpression>> paramList = Collections.<Pair<VarIdentifier,TypeExpression>>emptyList();
}
{
<LEFTPAREN> (paramList = FunctionParameterList())? <RIGHTPAREN>
@@ -1241,33 +1258,38 @@
}
}
-List<Pair<VarIdentifier,IndexedTypeExpression>> FunctionParameterList() :
+List<Pair<VarIdentifier,TypeExpression>> FunctionParameterList() :
{
- List<Pair<VarIdentifier,IndexedTypeExpression>> paramList = new ArrayList<Pair<VarIdentifier,IndexedTypeExpression>>();
- Pair<VarIdentifier,IndexedTypeExpression> varPair = new Pair<VarIdentifier,IndexedTypeExpression>(null,null);
- String var = null;
- IndexedTypeExpression type = null;
+ List<Pair<VarIdentifier,TypeExpression>> paramList = new ArrayList<Pair<VarIdentifier,TypeExpression>>();
+ Pair<VarIdentifier,TypeExpression> param = null;
}
{
- var = VariableIdentifier() {
- varPair.setFirst(new VarIdentifier(var));
- paramList.add(varPair);
- } (LOOKAHEAD(3)(<COLON>)? type = IndexedTypeExpr() {varPair.setSecond(type);} )? (<COMMA> var = VariableIdentifier() {
- varPair = new Pair<VarIdentifier,IndexedTypeExpression>(null,null);
- varPair.setFirst(new VarIdentifier(var));
- paramList.add(varPair);
- } (LOOKAHEAD(3)(<COLON>)? type = IndexedTypeExpr() {varPair.setSecond(type);})?)*
- {
- return paramList;
- }
+ param = FunctionParameter() { paramList.add(param); }
+ ( <COMMA> param = FunctionParameter() { paramList.add(param); } )*
+ {
+ return paramList;
+ }
}
-IndexedTypeExpression FunctionReturnType() throws ParseException:
+Pair<VarIdentifier,TypeExpression> FunctionParameter() throws ParseException:
{
- IndexedTypeExpression returnType = null;
+ String name = null;
+ TypeExpression type = null;
}
{
- ( LOOKAHEAD({laIdentifier(RETURNS)}) <IDENTIFIER> returnType = IndexedTypeExpr() )?
+ name = VariableIdentifier()
+ ( LOOKAHEAD(3) (<COLON>)? type = TypeExpr(false) )?
+ {
+ return new Pair<VarIdentifier,TypeExpression>(new VarIdentifier(name), type);
+ }
+}
+
+TypeExpression FunctionReturnType() throws ParseException:
+{
+ TypeExpression returnType = null;
+}
+{
+ ( LOOKAHEAD({laIdentifier(RETURNS)}) <IDENTIFIER> returnType = TypeExpr(false) )?
{
return returnType;
}
@@ -2124,27 +2146,27 @@
boolean isUnknownable = false;
}
{
- (
- typeExpr = TypeReference()
- | typeExpr = OrderedListTypeDef()
- | typeExpr = UnorderedListTypeDef()
- )
+ typeExpr = TypeExpr(false)
( <QUES> { isUnknownable = true; } )?
{
return new IndexedTypeExpression(typeExpr, isUnknownable);
}
}
-TypeExpression TypeExpr() throws ParseException:
+TypeExpression TypeExpr(boolean allowRecordTypeDef) throws ParseException:
{
TypeExpression typeExpr = null;
}
{
(
- typeExpr = RecordTypeDef()
- | typeExpr = TypeReference()
- | typeExpr = OrderedListTypeDef()
- | typeExpr = UnorderedListTypeDef()
+ typeExpr = TypeReference()
+ | typeExpr = OrderedListTypeDef(allowRecordTypeDef)
+ | typeExpr = UnorderedListTypeDef(allowRecordTypeDef)
+ | typeExpr = RecordTypeDef() {
+ if (!allowRecordTypeDef) {
+ throw new SqlppParseException(typeExpr.getSourceLocation(), "Unexpected record type declaration");
+ }
+ }
)
{
return typeExpr;
@@ -2218,7 +2240,7 @@
SqlppHint.DATE_BETWEEN_YEARS_HINT, SqlppHint.DATETIME_ADD_RAND_HOURS_HINT, SqlppHint.AUTO_HINT);
IRecordFieldDataGen rfdg = hintToken != null ? parseFieldDataGen(hintToken) : null;
}
- <COLON> type = TypeExpr() ( <QUES> { nullable = true; missable = true; } )?
+ <COLON> type = TypeExpr(true) ( <QUES> { nullable = true; missable = true; } )?
{
recType.addField(fieldName, type, nullable, missable, rfdg);
}
@@ -2240,14 +2262,14 @@
}
}
-OrderedListTypeDefinition OrderedListTypeDef() throws ParseException:
+OrderedListTypeDefinition OrderedListTypeDef(boolean allowRecordTypeDef) throws ParseException:
{
Token startToken = null;
TypeExpression type = null;
}
{
<LEFTBRACKET> { startToken = token; }
- ( type = TypeExpr() )
+ ( type = TypeExpr(allowRecordTypeDef) )
<RIGHTBRACKET>
{
OrderedListTypeDefinition typeDef = new OrderedListTypeDefinition(type);
@@ -2255,14 +2277,14 @@
}
}
-UnorderedListTypeDefinition UnorderedListTypeDef() throws ParseException:
+UnorderedListTypeDefinition UnorderedListTypeDef(boolean allowRecordTypeDef) throws ParseException:
{
Token startToken = null;
TypeExpression type = null;
}
{
<LEFTDBLBRACE> { startToken = token; }
- ( type = TypeExpr() )
+ ( type = TypeExpr(allowRecordTypeDef) )
<RIGHTDBLBRACE>
{
UnorderedListTypeDefinition typeDef = new UnorderedListTypeDefinition(type);
@@ -2498,8 +2520,7 @@
{
Token startToken = null;
String functionName;
- List<Pair<VarIdentifier,IndexedTypeExpression>> paramList = Collections.<Pair<VarIdentifier,IndexedTypeExpression>>emptyList();;
- List<VarIdentifier> paramVarOnly = new ArrayList<VarIdentifier>();
+ List<Pair<VarIdentifier,TypeExpression>> paramList;
Expression funcBody;
createNewScope();
}
@@ -2513,10 +2534,12 @@
{
FunctionSignature signature = new FunctionSignature(defaultDataverse, functionName, paramList.size());
getCurrentScope().addFunctionDescriptor(signature, false);
- for(Pair<VarIdentifier,IndexedTypeExpression> p: paramList){
- paramVarOnly.add(p.getFirst());
+ ensureNoTypeDeclsInFunction(functionName, paramList, null, startToken);
+ List<VarIdentifier> params = new ArrayList<VarIdentifier>(paramList.size());
+ for (Pair<VarIdentifier,TypeExpression> p: paramList) {
+ params.add(p.getFirst());
}
- FunctionDecl stmt = new FunctionDecl(signature, paramVarOnly, funcBody);
+ FunctionDecl stmt = new FunctionDecl(signature, params, funcBody);
removeCurrentScope();
return addSourceLocation(stmt, startToken);
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
index f134ee5..e06e22f 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
@@ -55,7 +55,6 @@
import org.apache.asterix.metadata.entities.Node;
import org.apache.asterix.metadata.entities.NodeGroup;
import org.apache.asterix.metadata.entities.Synonym;
-import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.transaction.management.opcallbacks.AbstractIndexModificationOperationCallback.Operation;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.api.exceptions.HyracksDataException;
@@ -383,14 +382,7 @@
datatype = cache.getDatatype(dataverseName, datatypeName);
if (datatype != null) {
// Datatype is already in the cache, don't add it again.
- // create a new Datatype object with a new ARecordType object in order to avoid
- // concurrent access to UTF8StringPointable comparator in ARecordType object.
- // see issue 510
- ARecordType aRecType = (ARecordType) datatype.getDatatype();
- return new Datatype(
- datatype.getDataverseName(), datatype.getDatatypeName(), new ARecordType(aRecType.getTypeName(),
- aRecType.getFieldNames(), aRecType.getFieldTypes(), aRecType.isOpen()),
- datatype.getIsAnonymous());
+ return datatype;
}
try {
datatype = metadataNode.getDatatype(ctx.getTxnId(), dataverseName, datatypeName);
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java
index 3e8f3ba..1962559 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java
@@ -95,6 +95,7 @@
public static final String FIELD_NAME_PROPERTIES = "Properties";
public static final String FIELD_NAME_RECORD = "Record";
public static final String FIELD_NAME_RETURN_TYPE = "ReturnType";
+ public static final String FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME = "ReturnTypeDataverseName";
public static final String FIELD_NAME_SEARCH_KEY = "SearchKey";
public static final String FIELD_NAME_STATUS = "Status";
public static final String FIELD_NAME_SYNONYM_NAME = "SynonymName";
@@ -341,7 +342,6 @@
//open types
public static final String FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME = "WithParams";
public static final String FUNCTION_ARECORD_FUNCTION_LIBRARY_FIELD_NAME = "Library";
- public static final String FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_IS_NULLABLE = "ReturnTypeIsNullable";
public static final String FUNCTION_ARECORD_FUNCTION_NULLCALL_FIELD_NAME = "NullCall";
public static final String FUNCTION_ARECORD_FUNCTION_DETERMINISTIC_FIELD_NAME = "Deterministic";
public static final String FUNCTION_ARECORD_FUNCTION_PARAMTYPES_FIELD_NAME = "ParamTypes";
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/BuiltinTypeMap.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/BuiltinTypeMap.java
index e26dec7..2dcea99 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/BuiltinTypeMap.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/BuiltinTypeMap.java
@@ -81,14 +81,13 @@
}
private BuiltinTypeMap() {
-
}
- public static IAType getBuiltinType(String typeName) {
+ public static BuiltinType getBuiltinType(String typeName) {
return _builtinTypeMap.get(typeName.toLowerCase());
}
- public static Set<IAType> getAllBuiltinTypes() {
+ public static Set<BuiltinType> getAllBuiltinTypes() {
return new HashSet<>(_builtinTypeMap.values());
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Function.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Function.java
index 6884970..542bbaf 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Function.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Function.java
@@ -20,7 +20,6 @@
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,32 +27,32 @@
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.metadata.MetadataCache;
import org.apache.asterix.metadata.api.IMetadataEntity;
-import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.TypeSignature;
import org.apache.hyracks.algebricks.common.utils.Triple;
public class Function implements IMetadataEntity<Function> {
- private static final long serialVersionUID = 3L;
+ private static final long serialVersionUID = 4L;
private final FunctionSignature signature;
- private final List<String> argNames;
- private final List<IAType> argTypes;
- private final IAType returnType;
+ private final List<String> paramNames;
+ private final List<TypeSignature> paramTypes;
+ private final TypeSignature returnType;
private final String body;
private final String language;
private final String kind;
private final String library;
private final Boolean deterministic; // null for SQL++ and AQL functions
private final Boolean nullCall; // null for SQL++ and AQL functions
- private final Map<String, String> params;
+ private final Map<String, String> resources;
private final List<List<Triple<DataverseName, String, String>>> dependencies;
- public Function(FunctionSignature signature, List<String> argNames, List<IAType> argTypes, IAType returnType,
- String functionBody, String functionKind, String language, String library, Boolean nullCall,
- Boolean deterministic, Map<String, String> params,
+ public Function(FunctionSignature signature, List<String> paramNames, List<TypeSignature> paramTypes,
+ TypeSignature returnType, String functionBody, String functionKind, String language, String library,
+ Boolean nullCall, Boolean deterministic, Map<String, String> resources,
List<List<Triple<DataverseName, String, String>>> dependencies) {
this.signature = signature;
- this.argNames = argNames;
- this.argTypes = argTypes;
+ this.paramNames = paramNames;
+ this.paramTypes = paramTypes;
this.body = functionBody;
this.returnType = returnType;
this.language = language;
@@ -61,7 +60,7 @@
this.library = library;
this.nullCall = nullCall;
this.deterministic = deterministic;
- this.params = params == null ? new HashMap<>() : params;
+ this.resources = resources == null ? Collections.emptyMap() : resources;
this.dependencies = dependencies == null
? Arrays.asList(Collections.emptyList(), Collections.emptyList(), Collections.emptyList())
: dependencies;
@@ -83,19 +82,19 @@
return signature.getArity();
}
- public List<String> getArgNames() {
- return argNames;
+ public List<String> getParameterNames() {
+ return paramNames;
}
- public List<IAType> getArgTypes() {
- return argTypes;
+ public List<TypeSignature> getParameterTypes() {
+ return paramTypes;
}
public String getFunctionBody() {
return body;
}
- public IAType getReturnType() {
+ public TypeSignature getReturnType() {
return returnType;
}
@@ -123,8 +122,8 @@
return deterministic;
}
- public Map<String, String> getParams() {
- return params;
+ public Map<String, String> getResources() {
+ return resources;
}
public List<List<Triple<DataverseName, String, String>>> getDependencies() {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/FunctionTupleTranslator.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/FunctionTupleTranslator.java
index f4f6070..7135305 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/FunctionTupleTranslator.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/FunctionTupleTranslator.java
@@ -19,15 +19,15 @@
package org.apache.asterix.metadata.entitytupletranslators;
-import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_IS_NULLABLE;
+import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_DATAVERSE_NAME;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_NAME;
+import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_TYPE;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_VALUE;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DETERMINISTIC_FIELD_NAME;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_LIBRARY_FIELD_NAME;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_NULLCALL_FIELD_NAME;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAMTYPES_FIELD_NAME;
-import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_IS_NULLABLE;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.PROPERTIES_NAME_FIELD_NAME;
import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.PROPERTIES_VALUE_FIELD_NAME;
@@ -58,13 +58,8 @@
import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
import org.apache.asterix.om.types.AOrderedListType;
import org.apache.asterix.om.types.ARecordType;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.AUnionType;
-import org.apache.asterix.om.types.AbstractComplexType;
import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.om.utils.NonTaggedFormatUtil;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.asterix.om.types.TypeSignature;
import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
@@ -98,7 +93,7 @@
}
}
- protected Function createMetadataEntityFromARecord(ARecord functionRecord) throws AlgebricksException {
+ protected Function createMetadataEntityFromARecord(ARecord functionRecord) {
String dataverseCanonicalName =
((AString) functionRecord.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_DATAVERSENAME_FIELD_INDEX))
.getStringValue();
@@ -109,19 +104,19 @@
int arity = Integer.parseInt(((AString) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_ARITY_FIELD_INDEX)).getStringValue());
- IACursor argCursor = ((AOrderedList) functionRecord
+ IACursor paramNameCursor = ((AOrderedList) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX)).getCursor();
- List<String> argNames = new ArrayList<>();
- while (argCursor.next()) {
- argNames.add(((AString) argCursor.get()).getStringValue());
+ List<String> paramNames = new ArrayList<>();
+ while (paramNameCursor.next()) {
+ paramNames.add(((AString) paramNameCursor.get()).getStringValue());
}
- List<IAType> argTypes = getArgTypes(functionRecord, dataverseName, arity);
+ List<TypeSignature> paramTypes = getParamTypes(functionRecord, arity, dataverseName);
String returnTypeName = ((AString) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX)).getStringValue();
- Boolean returnTypeIsNullable = getBoolean(functionRecord, FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_IS_NULLABLE);
- IAType returnType = resolveType(dataverseName, returnTypeName, returnTypeIsNullable);
+ String returnTypeDataverseNameCanonical = getString(functionRecord, FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME);
+ TypeSignature returnType = getTypeSignature(returnTypeName, returnTypeDataverseNameCanonical, dataverseName);
String definition = ((AString) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEFINITION_FIELD_INDEX)).getStringValue();
@@ -134,7 +129,7 @@
Boolean nullCall = getBoolean(functionRecord, FUNCTION_ARECORD_FUNCTION_NULLCALL_FIELD_NAME);
Boolean deterministic = getBoolean(functionRecord, FUNCTION_ARECORD_FUNCTION_DETERMINISTIC_FIELD_NAME);
- Map<String, String> params = getWithParameters(functionRecord);
+ Map<String, String> resources = getResources(functionRecord);
IACursor dependenciesCursor = ((AOrderedList) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEPENDENCIES_FIELD_INDEX)).getCursor();
@@ -152,23 +147,12 @@
FunctionSignature signature = new FunctionSignature(dataverseName, functionName, arity);
- return new Function(signature, argNames, argTypes, returnType, definition, functionKind, language,
- functionLibrary, nullCall, deterministic, params, dependencies);
+ return new Function(signature, paramNames, paramTypes, returnType, definition, functionKind, language,
+ functionLibrary, nullCall, deterministic, resources, dependencies);
}
- private IAType resolveType(DataverseName dataverseName, String typeName, Boolean isUnknownable)
- throws AlgebricksException {
- //TODO(dmitry): revisit "isNullable"/"isMissable" for function paramters
- return BuiltinType.ANY.getTypeName().equalsIgnoreCase(typeName) ? BuiltinType.ANY
- : TypeUtil.createQuantifiedType(
- BuiltinTypeMap.getTypeFromTypeName(metadataNode, txnId, dataverseName, typeName), isUnknownable,
- isUnknownable);
- }
-
- private List<IAType> getArgTypes(ARecord functionRecord, DataverseName dataverseName, int arity)
- throws AlgebricksException {
- List<IAType> argTypes = new ArrayList<>(arity);
-
+ private List<TypeSignature> getParamTypes(ARecord functionRecord, int arity, DataverseName functionDataverseName) {
+ List<TypeSignature> paramTypes = new ArrayList<>(arity);
ARecordType functionRecordType = functionRecord.getType();
int paramTypesFieldIdx = functionRecordType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_PARAMTYPES_FIELD_NAME);
if (paramTypesFieldIdx >= 0) {
@@ -176,17 +160,31 @@
while (cursor.next()) {
ARecord paramTypeRecord = (ARecord) cursor.get();
String paramTypeName = getString(paramTypeRecord, FIELD_NAME_TYPE);
- Boolean paramTypeIsNullable = getBoolean(paramTypeRecord, FIELD_NAME_IS_NULLABLE);
- IAType paramType = paramTypeName != null
- ? resolveType(dataverseName, paramTypeName, paramTypeIsNullable) : BuiltinType.ANY;
- argTypes.add(paramType);
+ String paramTypeDataverseNameCanonical = getString(paramTypeRecord, FIELD_NAME_DATAVERSE_NAME);
+ TypeSignature paramType =
+ getTypeSignature(paramTypeName, paramTypeDataverseNameCanonical, functionDataverseName);
+ paramTypes.add(paramType);
}
} else {
for (int i = 0; i < arity; i++) {
- argTypes.add(BuiltinType.ANY);
+ paramTypes.add(TypeUtil.ANY_TYPE_SIGNATURE);
}
}
- return argTypes;
+ return paramTypes;
+ }
+
+ private TypeSignature getTypeSignature(String typeName, String typeDataverseNameCanonical,
+ DataverseName functionDataverseName) {
+ if (BuiltinType.ANY.getTypeName().equals(typeName)) {
+ return TypeUtil.ANY_TYPE_SIGNATURE;
+ }
+ BuiltinType builtinType = BuiltinTypeMap.getBuiltinType(typeName);
+ if (builtinType != null) {
+ return new TypeSignature(builtinType);
+ }
+ DataverseName typeDataverseName = typeDataverseNameCanonical == null ? functionDataverseName
+ : DataverseName.createFromCanonicalForm(typeDataverseNameCanonical);
+ return new TypeSignature(typeDataverseName, typeName);
}
private Triple<DataverseName, String, String> getDependency(AOrderedList dependencySubnames) {
@@ -203,7 +201,7 @@
return new Triple<>(dataverseName, second, third);
}
- private Map<String, String> getWithParameters(ARecord functionRecord) {
+ private Map<String, String> getResources(ARecord functionRecord) {
Map<String, String> adaptorConfiguration = new HashMap<>();
final ARecordType functionType = functionRecord.getType();
final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME);
@@ -278,7 +276,7 @@
ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
listBuilder.reset((AOrderedListType) MetadataRecordTypes.FUNCTION_RECORDTYPE
.getFieldTypes()[MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX]);
- for (String p : function.getArgNames()) {
+ for (String p : function.getParameterNames()) {
itemValue.reset();
aString.setValue(p);
stringSerde.serialize(aString, itemValue.getDataOutput());
@@ -288,17 +286,10 @@
listBuilder.write(fieldValue.getDataOutput(), true);
recordBuilder.addField(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX, fieldValue);
- IAType returnType = function.getReturnType();
- boolean returnTypeIsUnknownable = NonTaggedFormatUtil.isOptional(returnType);
- IAType returnPrimeType = returnTypeIsUnknownable ? ((AUnionType) returnType).getActualType() : returnType;
- if (returnPrimeType.getTypeTag().isDerivedType()) {
- handleNestedDerivedType(dataverseName, returnPrimeType.getTypeName(),
- (AbstractComplexType) returnPrimeType);
- }
-
// write field 4
+ // Note: return type's dataverse name is written later in the open part
fieldValue.reset();
- aString.setValue(returnPrimeType.getTypeName());
+ aString.setValue(function.getReturnType().getName());
stringSerde.serialize(aString, fieldValue.getDataOutput());
recordBuilder.addField(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX, fieldValue);
@@ -347,7 +338,7 @@
dependenciesListBuilder.write(fieldValue.getDataOutput(), true);
recordBuilder.addField(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEPENDENCIES_FIELD_INDEX, fieldValue);
- writeOpenFields(function, returnPrimeType, returnTypeIsUnknownable);
+ writeOpenFields(function);
// write record
recordBuilder.write(tupleBuilder.getDataOutput(), true);
@@ -357,18 +348,17 @@
return tuple;
}
- protected void writeOpenFields(Function function, IAType returnPrimeType, boolean returnTypeIsUnknownable)
- throws HyracksDataException {
- writeReturnTypeIsNullable(returnPrimeType, returnTypeIsUnknownable);
- writeArgTypes(function);
- writeWithParameters(function);
+ protected void writeOpenFields(Function function) throws HyracksDataException {
+ writeReturnTypeDataverseName(function);
+ writeParameterTypes(function);
+ writeResources(function);
writeLibrary(function);
writeNullCall(function);
writeDeterministic(function);
}
- protected void writeWithParameters(Function function) throws HyracksDataException {
- Map<String, String> withParams = function.getParams();
+ protected void writeResources(Function function) throws HyracksDataException {
+ Map<String, String> withParams = function.getResources();
if (withParams == null || withParams.isEmpty()) {
return;
}
@@ -391,19 +381,14 @@
recordBuilder.addField(fieldName, fieldValue);
}
- protected void writeArgTypes(Function function) throws HyracksDataException {
- DataverseName dataverseName = function.getDataverseName();
+ protected void writeParameterTypes(Function function) throws HyracksDataException {
OrderedListBuilder listBuilder = new OrderedListBuilder();
ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
listBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
- for (IAType argType : function.getArgTypes()) {
- boolean argTypeIsUnknownable = NonTaggedFormatUtil.isOptional(argType);
- IAType argPrimeType = argTypeIsUnknownable ? ((AUnionType) argType).getActualType() : argType;
- if (argPrimeType.getTypeTag().isDerivedType()) {
- handleNestedDerivedType(dataverseName, argPrimeType.getTypeName(), (AbstractComplexType) argPrimeType);
- }
+ for (TypeSignature paramType : function.getParameterTypes()) {
itemValue.reset();
- writeTypeRecord(argPrimeType, argTypeIsUnknownable, itemValue.getDataOutput());
+ writeTypeRecord(paramType.getDataverseName(), paramType.getName(), function.getDataverseName(),
+ itemValue.getDataOutput());
listBuilder.addItem(itemValue);
}
fieldValue.reset();
@@ -429,14 +414,17 @@
recordBuilder.addField(fieldName, fieldValue);
}
- protected void writeReturnTypeIsNullable(IAType returnPrimeType, boolean returnTypeIsUnknownable)
- throws HyracksDataException {
- if (returnPrimeType.getTypeTag() != ATypeTag.ANY) {
+ protected void writeReturnTypeDataverseName(Function function) throws HyracksDataException {
+ DataverseName returnTypeDataverseName = function.getReturnType().getDataverseName();
+ boolean skipReturnTypeDataverseName =
+ returnTypeDataverseName == null || returnTypeDataverseName.equals(function.getDataverseName());
+ if (!skipReturnTypeDataverseName) {
fieldName.reset();
- aString.setValue(FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_IS_NULLABLE);
+ aString.setValue(FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
- booleanSerde.serialize(ABoolean.valueOf(returnTypeIsUnknownable), fieldValue.getDataOutput());
+ aString.setValue(returnTypeDataverseName.getCanonicalForm());
+ stringSerde.serialize(aString, fieldValue.getDataOutput());
recordBuilder.addField(fieldName, fieldValue);
}
}
@@ -492,7 +480,8 @@
propertyRecordBuilder.write(out, true);
}
- public void writeTypeRecord(IAType primeType, boolean isUnknownable, DataOutput out) throws HyracksDataException {
+ public void writeTypeRecord(DataverseName typeDataverseName, String typeName, DataverseName functionDataverseName,
+ DataOutput out) throws HyracksDataException {
IARecordBuilder propertyRecordBuilder = new RecordBuilder();
propertyRecordBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
@@ -501,17 +490,19 @@
aString.setValue(FIELD_NAME_TYPE);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
- aString.setValue(primeType.getTypeName());
+ aString.setValue(typeName);
stringSerde.serialize(aString, fieldValue.getDataOutput());
propertyRecordBuilder.addField(fieldName, fieldValue);
- // write field "IsNullable"
- if (primeType.getTypeTag() != ATypeTag.ANY) {
+ // write field "DataverseName"
+ boolean skipTypeDataverseName = typeDataverseName == null || typeDataverseName.equals(functionDataverseName);
+ if (!skipTypeDataverseName) {
fieldName.reset();
- aString.setValue(FIELD_NAME_IS_NULLABLE);
+ aString.setValue(FIELD_NAME_DATAVERSE_NAME);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
- booleanSerde.serialize(ABoolean.valueOf(isUnknownable), fieldValue.getDataOutput());
+ aString.setValue(typeDataverseName.getCanonicalForm());
+ stringSerde.serialize(aString, fieldValue.getDataOutput());
propertyRecordBuilder.addField(fieldName, fieldValue);
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java
index ced8dc0..6c88621 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.metadata.functions;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -26,10 +27,13 @@
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.functions.ExternalFunctionLanguage;
import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.metadata.MetadataTransactionContext;
+import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.metadata.entities.BuiltinTypeMap;
import org.apache.asterix.metadata.entities.Function;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.TypeSignature;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
@@ -40,31 +44,38 @@
// do nothing
}
- public static IFunctionInfo getExternalFunctionInfo(MetadataTransactionContext txnCtx, Function function)
+ public static IFunctionInfo getExternalFunctionInfo(MetadataProvider metadataProvider, Function function)
throws AlgebricksException {
String functionKind = function.getKind();
IFunctionInfo finfo = null;
if (FunctionKind.SCALAR.toString().equalsIgnoreCase(functionKind)) {
- finfo = getScalarFunctionInfo(txnCtx, function);
+ finfo = getScalarFunctionInfo(metadataProvider, function);
} else if (FunctionKind.AGGREGATE.toString().equalsIgnoreCase(functionKind)) {
- finfo = getAggregateFunctionInfo(txnCtx, function);
+ finfo = getAggregateFunctionInfo(metadataProvider, function);
} else if (FunctionKind.STATEFUL.toString().equalsIgnoreCase(functionKind)) {
- finfo = getStatefulFunctionInfo(txnCtx, function);
+ finfo = getStatefulFunctionInfo(metadataProvider, function);
} else if (FunctionKind.UNNEST.toString().equalsIgnoreCase(functionKind)) {
- finfo = getUnnestFunctionInfo(txnCtx, function);
+ finfo = getUnnestFunctionInfo(metadataProvider, function);
}
return finfo;
}
- private static IFunctionInfo getScalarFunctionInfo(MetadataTransactionContext txnCtx, Function function)
+ private static IFunctionInfo getScalarFunctionInfo(MetadataProvider metadataProvider, Function function)
throws AlgebricksException {
if (function.getDeterministic() == null) {
throw new AsterixException(ErrorCode.METADATA_ERROR, "");
}
- IAType returnType = function.getReturnType();
- IResultTypeComputer typeComputer = new ExternalTypeComputer(returnType, function.getArgTypes());
+ List<IAType> paramTypes = new ArrayList<>(function.getParameterTypes().size());
+ for (TypeSignature ts : function.getParameterTypes()) {
+ IAType paramType = resolveFunctionType(ts, metadataProvider);
+ paramTypes.add(paramType);
+ }
+
+ IAType returnType = resolveFunctionType(function.getReturnType(), metadataProvider);
+
+ IResultTypeComputer typeComputer = new ExternalTypeComputer(returnType, paramTypes);
ExternalFunctionLanguage lang;
try {
@@ -75,22 +86,35 @@
List<String> externalIdentifier = decodeExternalIdentifier(lang, function.getFunctionBody());
return new ExternalScalarFunctionInfo(function.getSignature().createFunctionIdentifier(), returnType,
- externalIdentifier, lang, function.getLibrary(), function.getArgTypes(), function.getParams(),
+ externalIdentifier, lang, function.getLibrary(), paramTypes, function.getResources(),
function.getDeterministic(), typeComputer);
}
- private static IFunctionInfo getUnnestFunctionInfo(MetadataTransactionContext txnCtx, Function function) {
+ private static IFunctionInfo getUnnestFunctionInfo(MetadataProvider metadataProvider, Function function) {
return null;
}
- private static IFunctionInfo getStatefulFunctionInfo(MetadataTransactionContext txnCtx, Function function) {
+ private static IFunctionInfo getStatefulFunctionInfo(MetadataProvider metadataProvider, Function function) {
return null;
}
- private static IFunctionInfo getAggregateFunctionInfo(MetadataTransactionContext txnCtx, Function function) {
+ private static IFunctionInfo getAggregateFunctionInfo(MetadataProvider metadataProvider, Function function) {
return null;
}
+ private static IAType resolveFunctionType(TypeSignature typeSignature, MetadataProvider metadataProvider)
+ throws AlgebricksException {
+ String typeName = typeSignature.getName();
+ if (BuiltinType.ANY.getTypeName().equals(typeName)) {
+ return BuiltinType.ANY;
+ }
+ IAType type = BuiltinTypeMap.getBuiltinType(typeName);
+ if (type == null) {
+ type = metadataProvider.findType(typeSignature.getDataverseName(), typeName);
+ }
+ return type;
+ }
+
public static String encodeExternalIdentifier(FunctionSignature functionSignature,
ExternalFunctionLanguage language, List<String> identList) throws AlgebricksException {
switch (language) {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java
index 2f5742e..4a000a3 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java
@@ -22,6 +22,8 @@
import org.apache.asterix.om.exceptions.TypeMismatchException;
import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -32,22 +34,23 @@
public class ExternalTypeComputer extends AbstractResultTypeComputer {
private IAType resultType;
- private List<IAType> argTypes;
+ private List<IAType> paramPrimeTypes;
@Override
protected void checkArgType(FunctionIdentifier funcId, int argIndex, IAType type, SourceLocation sourceLoc)
throws AlgebricksException {
- IAType reqArgType = argTypes.get(argIndex);
- if (!type.equals(argTypes.get(argIndex))
- && !ATypeHierarchy.isCompatible(type.getTypeTag(), reqArgType.getTypeTag())) {
+ IAType reqParamType = paramPrimeTypes.get(argIndex);
+ if (!type.equals(paramPrimeTypes.get(argIndex))
+ && !ATypeHierarchy.isCompatible(type.getTypeTag(), reqParamType.getTypeTag())) {
throw new TypeMismatchException(sourceLoc, funcId, argIndex, type.getTypeTag(),
- argTypes.get(argIndex).getTypeTag());
+ paramPrimeTypes.get(argIndex).getTypeTag());
}
}
- public ExternalTypeComputer(IAType resultType, List<IAType> argTypes) {
- this.resultType = resultType;
- this.argTypes = argTypes;
+ public ExternalTypeComputer(IAType resultPrimeType, List<IAType> paramPrimeTypes) {
+ this.resultType = resultPrimeType.getTypeTag() == ATypeTag.ANY ? resultPrimeType
+ : AUnionType.createUnknownableType(resultPrimeType);
+ this.paramPrimeTypes = paramPrimeTypes;
}
@Override
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java
index 78c026d..3b312bb 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java
@@ -100,8 +100,6 @@
*/
public static final byte OP_UPSERT = 0x03;
- private static final String DATASET_INLINE_TYPE_PREFIX = "$d$t$";
-
private DatasetUtil() {
}
@@ -596,12 +594,4 @@
return nodeGroup;
}
- public static String createInlineTypeName(String datasetName, boolean forMetaItemType) {
- char typeChar = forMetaItemType ? 'm' : 'i';
- return DATASET_INLINE_TYPE_PREFIX + typeChar + '$' + datasetName;
- }
-
- public static boolean isInlineTypeName(Dataset dataset, DataverseName typeDataverseName, String typeName) {
- return dataset.getDataverseName().equals(typeDataverseName) && typeName.startsWith(DATASET_INLINE_TYPE_PREFIX);
- }
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java
index 4c3ad73..11dc1ee 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java
@@ -26,12 +26,16 @@
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.metadata.entities.Dataset;
import org.apache.asterix.metadata.entities.Index;
import org.apache.asterix.om.typecomputer.impl.TypeComputeUtils;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.ATypeTag;
import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.TypeSignature;
import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -42,6 +46,14 @@
*/
public class TypeUtil {
+ public static final TypeSignature ANY_TYPE_SIGNATURE = new TypeSignature(BuiltinType.ANY);
+
+ private static final char TYPE_NAME_DELIMITER = '$';
+
+ private static final String DATASET_INLINE_TYPE_PREFIX = "$d$t$";
+
+ private static final String FUNCTION_INLINE_TYPE_PREFIX = "$f$t$";
+
private TypeUtil() {
}
@@ -240,4 +252,29 @@
}
return resType;
}
+
+ public static boolean isReservedInlineTypeName(String typeName) {
+ return typeName.length() > 0 && typeName.charAt(0) == TYPE_NAME_DELIMITER;
+ }
+
+ public static String createDatasetInlineTypeName(String datasetName, boolean forMetaItemType) {
+ char typeChar = forMetaItemType ? 'm' : 'i';
+ return DATASET_INLINE_TYPE_PREFIX + typeChar + TYPE_NAME_DELIMITER + datasetName;
+ }
+
+ public static boolean isDatasetInlineTypeName(Dataset dataset, DataverseName typeDataverseName, String typeName) {
+ return dataset.getDataverseName().equals(typeDataverseName) && typeName.startsWith(DATASET_INLINE_TYPE_PREFIX);
+ }
+
+ public static String createFunctionParameterTypeName(String functionName, int arity, int parameterIndex) {
+ StringBuilder sb = new StringBuilder(FUNCTION_INLINE_TYPE_PREFIX.length() + functionName.length() + 8);
+ sb.append(FUNCTION_INLINE_TYPE_PREFIX).append(functionName).append(TYPE_NAME_DELIMITER).append(arity);
+ if (parameterIndex >= 0) {
+ sb.append(TYPE_NAME_DELIMITER).append(parameterIndex);
+ } else if (parameterIndex != -1) {
+ throw new IllegalArgumentException(String.valueOf(parameterIndex));
+ } // otherwise it's a return type
+
+ return sb.toString();
+ }
}
diff --git a/asterixdb/asterix-metadata/src/test/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtilTest.java b/asterixdb/asterix-metadata/src/test/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtilTest.java
deleted file mode 100644
index 17b1213..0000000
--- a/asterixdb/asterix-metadata/src/test/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtilTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.asterix.metadata.functions;
-
-import java.util.LinkedList;
-
-import org.apache.asterix.common.functions.ExternalFunctionLanguage;
-import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.common.metadata.DataverseName;
-import org.apache.asterix.common.transactions.TxnId;
-import org.apache.asterix.metadata.MetadataTransactionContext;
-import org.apache.asterix.metadata.entities.Function;
-import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ExternalFunctionCompilerUtilTest {
- @Test
- public void test() throws AlgebricksException {
- // given
- MetadataTransactionContext txnCtx = new MetadataTransactionContext(new TxnId(1));
- FunctionSignature signature = new FunctionSignature(DataverseName.createSinglePartName("test"), "test", 0);
- Function function = new Function(signature, new LinkedList<>(), new LinkedList<>(), BuiltinType.ASTRING, "",
- "SCALAR", ExternalFunctionLanguage.JAVA.name(), "", false, false, null, null);
-
- // when
- ExternalScalarFunctionInfo info =
- (ExternalScalarFunctionInfo) ExternalFunctionCompilerUtil.getExternalFunctionInfo(txnCtx, function);
-
- // then
- IAType expectedType = BuiltinType.ASTRING;
- Assert.assertEquals(expectedType, info.getReturnType());
- }
-}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeSignature.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeSignature.java
index ac6af0a..682ec6a 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeSignature.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeSignature.java
@@ -18,20 +18,25 @@
*/
package org.apache.asterix.om.types;
+import java.io.Serializable;
import java.util.Objects;
import org.apache.asterix.common.metadata.DataverseName;
-public class TypeSignature {
+public class TypeSignature implements Serializable {
+
+ private static final long serialVersionUID = 1L;
private final DataverseName dataverseName;
private final String name;
- private final String alias;
public TypeSignature(DataverseName dataverseName, String name) {
this.dataverseName = dataverseName;
this.name = name;
- this.alias = (dataverseName != null ? dataverseName.getCanonicalForm() : null) + "@" + name;
+ }
+
+ public TypeSignature(BuiltinType builtinType) {
+ this(null, builtinType.getTypeName());
}
@Override
@@ -46,12 +51,12 @@
@Override
public String toString() {
- return alias;
+ return (dataverseName != null ? dataverseName.getCanonicalForm() : null) + "@" + name;
}
@Override
public int hashCode() {
- return alias.hashCode();
+ return Objects.hash(dataverseName, name);
}
public DataverseName getDataverseName() {
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/IOManager.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/IOManager.java
index c335312..6c35eff 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/IOManager.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/IOManager.java
@@ -81,7 +81,7 @@
for (IODeviceHandle d : ioDevices) {
if (d.getWorkspace() != null) {
try {
- FileUtil.forceMkdirs(new File(d.getMount(), d.getWorkspace()));
+ FileUtil.forceMkdirs(getWorkspaceFolder(d));
} catch (IOException e) {
throw HyracksDataException.create(e);
}
@@ -346,8 +346,13 @@
return dev.createFileRef(waPath + File.separator + waf.getName());
}
- public String getWorkspacePath(int index) {
- return workspaces.get(index) != null ? workspaces.get(index).getWorkspace() : null;
+ public File getWorkspacePath(int index) {
+ IODeviceHandle dev = workspaces.get(index);
+ return dev != null ? getWorkspaceFolder(dev) : null;
+ }
+
+ private File getWorkspaceFolder(IODeviceHandle dev) {
+ return new File(dev.getMount(), dev.getWorkspace());
}
@Override
@@ -367,7 +372,7 @@
@Override
public void deleteWorkspaceFiles() throws HyracksDataException {
for (IODeviceHandle ioDevice : workspaces) {
- File workspaceFolder = new File(ioDevice.getMount(), ioDevice.getWorkspace());
+ File workspaceFolder = getWorkspaceFolder(ioDevice);
if (workspaceFolder.exists() && workspaceFolder.isDirectory()) {
File[] workspaceFiles = workspaceFolder.listFiles(WORKSPACE_FILES_FILTER);
for (File workspaceFile : workspaceFiles) {