[NO ISSUE] Cleanup function metadata
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
1. Introduce AbstractDatatypeTupleTranslator to be used
as a base class by metadata entity translators that need
to write data types
2. Align type information stored in user defined function
metadata (return and parameter types) with how types are
stored for user defined types
3. Remove 'deterministic' and 'nullcall' modifiers from metadata
for inline functions because 'nullcall' is not applicable and
'deterministic' is supposed to be inferred by the compiler
4. Introduce FunctionLanguage enum to replace string constants
Change-Id: I2054dc7b13f31f33e57dca6da6d44ab95ac9bb4f
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/4924
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
Reviewed-by: Ian Maxon <imaxon@uci.edu>
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 3940364..9df621c 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,21 +896,13 @@
if (function == null) {
return null;
}
- AbstractFunctionCallExpression f;
- if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_JAVA)) {
- IFunctionInfo finfo = ExternalFunctionCompilerUtil
- .getExternalFunctionInfo(metadataProvider.getMetadataTxnContext(), function);
- f = new ScalarFunctionCallExpression(finfo, args);
- f.setSourceLocation(sourceLoc);
- } else if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_AQL)
- || function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_SQLPP)) {
- IFunctionInfo finfo = FunctionUtil.getFunctionInfo(signature);
- f = new ScalarFunctionCallExpression(finfo, args);
- f.setSourceLocation(sourceLoc);
- } else {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
- " User defined functions written in " + function.getLanguage() + " are not supported");
- }
+ IFunctionInfo finfo =
+ function.getLanguage().isExternal()
+ ? ExternalFunctionCompilerUtil
+ .getExternalFunctionInfo(metadataProvider.getMetadataTxnContext(), function)
+ : FunctionUtil.getFunctionInfo(signature);
+ AbstractFunctionCallExpression f = new ScalarFunctionCallExpression(finfo, args);
+ f.setSourceLocation(sourceLoc);
return f;
} catch (AlgebricksException e) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, e.getMessage(), e);
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/TypeTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/TypeTranslator.java
index 9e01f6a..fd434f4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/TypeTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/TypeTranslator.java
@@ -23,7 +23,6 @@
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -36,6 +35,7 @@
import org.apache.asterix.lang.common.expression.TypeExpression;
import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
import org.apache.asterix.lang.common.expression.UnorderedListTypeDefinition;
+import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.metadata.MetadataManager;
import org.apache.asterix.metadata.MetadataTransactionContext;
import org.apache.asterix.metadata.entities.BuiltinTypeMap;
@@ -50,41 +50,43 @@
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.common.utils.Pair;
public class TypeTranslator {
private TypeTranslator() {
}
- public static Map<TypeSignature, IAType> computeTypes(MetadataTransactionContext mdTxnCtx, TypeExpression typeExpr,
- String typeName, DataverseName typeDataverse) throws AlgebricksException {
+ public static Map<TypeSignature, IAType> computeTypes(DataverseName typeDataverse, String typeName,
+ TypeExpression typeExpr, DataverseName defaultDataverse, MetadataTransactionContext mdTxnCtx)
+ throws AlgebricksException {
Map<TypeSignature, IAType> typeMap = new HashMap<>();
- return computeTypes(mdTxnCtx, typeExpr, typeName, typeDataverse, typeMap);
+ computeTypes(typeDataverse, typeName, typeExpr, defaultDataverse, mdTxnCtx, typeMap);
+ return typeMap;
}
- public static Map<TypeSignature, IAType> computeTypes(MetadataTransactionContext mdTxnCtx, TypeExpression typeExpr,
- String typeName, DataverseName typeDataverse, Map<TypeSignature, IAType> typeMap)
+ public static void computeTypes(DataverseName typeDataverse, String typeName, TypeExpression typeExpr,
+ DataverseName defaultDataverse, MetadataTransactionContext mdTxnCtx, Map<TypeSignature, IAType> outTypeMap)
throws AlgebricksException {
Map<String, Map<ARecordType, List<Integer>>> incompleteFieldTypes = new HashMap<>();
Map<TypeSignature, List<AbstractCollectionType>> incompleteItemTypes = new HashMap<>();
Map<TypeSignature, List<TypeSignature>> incompleteTopLevelTypeReferences = new HashMap<>();
- firstPass(typeExpr, typeName, typeMap, incompleteFieldTypes, incompleteItemTypes,
- incompleteTopLevelTypeReferences, typeDataverse);
- secondPass(mdTxnCtx, typeMap, incompleteFieldTypes, incompleteItemTypes, incompleteTopLevelTypeReferences,
+ firstPass(typeDataverse, typeName, typeExpr, outTypeMap, incompleteFieldTypes, incompleteItemTypes,
+ incompleteTopLevelTypeReferences, defaultDataverse);
+ secondPass(mdTxnCtx, outTypeMap, incompleteFieldTypes, incompleteItemTypes, incompleteTopLevelTypeReferences,
typeDataverse);
- for (IAType type : typeMap.values()) {
+ for (IAType type : outTypeMap.values()) {
if (type.getTypeTag().isDerivedType()) {
((AbstractComplexType) type).generateNestedDerivedTypeNames();
}
}
- return typeMap;
}
- private static void firstPass(TypeExpression typeExpr, String typeName, Map<TypeSignature, IAType> typeMap,
- Map<String, Map<ARecordType, List<Integer>>> incompleteFieldTypes,
+ private static void firstPass(DataverseName typeDataverse, String typeName, TypeExpression typeExpr,
+ Map<TypeSignature, IAType> outTypeMap, Map<String, Map<ARecordType, List<Integer>>> incompleteFieldTypes,
Map<TypeSignature, List<AbstractCollectionType>> incompleteItemTypes,
- Map<TypeSignature, List<TypeSignature>> incompleteTopLevelTypeReferences, DataverseName typeDataverse)
+ Map<TypeSignature, List<TypeSignature>> incompleteTopLevelTypeReferences, DataverseName defaultDataverse)
throws AlgebricksException {
if (BuiltinTypeMap.getBuiltinType(typeName) != null) {
@@ -94,36 +96,34 @@
switch (typeExpr.getTypeKind()) {
case TYPEREFERENCE: {
TypeReferenceExpression tre = (TypeReferenceExpression) typeExpr;
- IAType t = solveTypeReference(
- new TypeSignature(tre.getIdent().first == null ? typeDataverse : tre.getIdent().first,
- tre.getIdent().second.getValue()),
- typeMap);
+ TypeSignature treSignature = createTypeSignature(tre, defaultDataverse);
+ IAType t = solveTypeReference(treSignature, outTypeMap);
if (t != null) {
- typeMap.put(typeSignature, t);
+ outTypeMap.put(typeSignature, t);
} else {
- addIncompleteTopLevelTypeReference(tre, incompleteTopLevelTypeReferences, typeDataverse);
+ addIncompleteTopLevelTypeReference(typeSignature, treSignature, incompleteTopLevelTypeReferences);
}
break;
}
case RECORD: {
RecordTypeDefinition rtd = (RecordTypeDefinition) typeExpr;
- ARecordType recType = computeRecordType(typeSignature, rtd, typeMap, incompleteFieldTypes,
+ ARecordType recType = computeRecordType(typeSignature, rtd, outTypeMap, incompleteFieldTypes,
incompleteItemTypes, typeDataverse);
- typeMap.put(typeSignature, recType);
+ outTypeMap.put(typeSignature, recType);
break;
}
case ORDEREDLIST: {
OrderedListTypeDefinition oltd = (OrderedListTypeDefinition) typeExpr;
- AOrderedListType olType = computeOrderedListType(typeSignature, oltd, typeMap, incompleteItemTypes,
+ AOrderedListType olType = computeOrderedListType(typeSignature, oltd, outTypeMap, incompleteItemTypes,
incompleteFieldTypes, typeDataverse);
- typeMap.put(typeSignature, olType);
+ outTypeMap.put(typeSignature, olType);
break;
}
case UNORDEREDLIST: {
UnorderedListTypeDefinition ultd = (UnorderedListTypeDefinition) typeExpr;
- AUnorderedListType ulType = computeUnorderedListType(typeSignature, ultd, typeMap, incompleteItemTypes,
- incompleteFieldTypes, typeDataverse);
- typeMap.put(typeSignature, ulType);
+ AUnorderedListType ulType = computeUnorderedListType(typeSignature, ultd, outTypeMap,
+ incompleteItemTypes, incompleteFieldTypes, typeDataverse);
+ outTypeMap.put(typeSignature, ulType);
break;
}
default: {
@@ -250,10 +250,8 @@
}
case TYPEREFERENCE: {
TypeReferenceExpression tre = (TypeReferenceExpression) tExpr;
- TypeSignature signature =
- new TypeSignature(tre.getIdent().first == null ? defaultDataverse : tre.getIdent().first,
- tre.getIdent().second.getValue());
- IAType tref = solveTypeReference(signature, typeMap);
+ TypeSignature treSignature = createTypeSignature(tre, defaultDataverse);
+ IAType tref = solveTypeReference(treSignature, typeMap);
if (tref != null) {
act.setItemType(tref);
} else {
@@ -270,45 +268,24 @@
private static void addIncompleteCollectionTypeReference(AbstractCollectionType collType,
TypeReferenceExpression tre, Map<TypeSignature, List<AbstractCollectionType>> incompleteItemTypes,
DataverseName defaultDataverse) {
- String typeName = tre.getIdent().second.getValue();
- TypeSignature typeSignature =
- new TypeSignature(tre.getIdent().first == null ? defaultDataverse : tre.getIdent().first, typeName);
- List<AbstractCollectionType> typeList = incompleteItemTypes.get(typeSignature);
- if (typeList == null) {
- typeList = new LinkedList<>();
- incompleteItemTypes.put(typeSignature, typeList);
- }
+ TypeSignature typeSignature = createTypeSignature(tre, defaultDataverse);
+ List<AbstractCollectionType> typeList =
+ incompleteItemTypes.computeIfAbsent(typeSignature, k -> new ArrayList<>());
typeList.add(collType);
}
private static void addIncompleteFieldTypeReference(ARecordType recType, int fldPosition,
TypeReferenceExpression tre, Map<String, Map<ARecordType, List<Integer>>> incompleteFieldTypes) {
String typeName = tre.getIdent().second.getValue();
- Map<ARecordType, List<Integer>> refMap = incompleteFieldTypes.get(typeName);
- if (refMap == null) {
- refMap = new HashMap<>();
- incompleteFieldTypes.put(typeName, refMap);
- }
- List<Integer> typeList = refMap.get(recType);
- if (typeList == null) {
- typeList = new ArrayList<>();
- refMap.put(recType, typeList);
- }
+ Map<ARecordType, List<Integer>> refMap = incompleteFieldTypes.computeIfAbsent(typeName, k -> new HashMap<>());
+ List<Integer> typeList = refMap.computeIfAbsent(recType, k -> new ArrayList<>());
typeList.add(fldPosition);
}
- private static void addIncompleteTopLevelTypeReference(TypeReferenceExpression tre,
- Map<TypeSignature, List<TypeSignature>> incompleteTopLevelTypeReferences, DataverseName defaultDataverse) {
- String name = tre.getIdent().second.getValue();
- TypeSignature typeSignature =
- new TypeSignature(tre.getIdent().first == null ? defaultDataverse : tre.getIdent().first, name);
- List<TypeSignature> refList = incompleteTopLevelTypeReferences.get(typeSignature);
- if (refList == null) {
- refList = new LinkedList<>();
- incompleteTopLevelTypeReferences
- .put(new TypeSignature(tre.getIdent().first == null ? defaultDataverse : tre.getIdent().first,
- tre.getIdent().second.getValue()), refList);
- }
+ private static void addIncompleteTopLevelTypeReference(TypeSignature typeSignature, TypeSignature treSignature,
+ Map<TypeSignature, List<TypeSignature>> incompleteTopLevelTypeReferences) {
+ List<TypeSignature> refList =
+ incompleteTopLevelTypeReferences.computeIfAbsent(treSignature, k -> new ArrayList<>());
refList.add(typeSignature);
}
@@ -348,9 +325,7 @@
switch (texpr.getTypeKind()) {
case TYPEREFERENCE: {
TypeReferenceExpression tre = (TypeReferenceExpression) texpr;
- TypeSignature signature =
- new TypeSignature(tre.getIdent().first == null ? defaultDataverse : tre.getIdent().first,
- tre.getIdent().second.getValue());
+ TypeSignature signature = createTypeSignature(tre, defaultDataverse);
IAType tref = solveTypeReference(signature, typeMap);
if (tref != null) {
if (!rtd.getOptionableFields().get(j)) { // not nullable
@@ -400,4 +375,10 @@
return recType;
}
+
+ private static TypeSignature createTypeSignature(TypeReferenceExpression tre, DataverseName defaultDataverse) {
+ Pair<DataverseName, Identifier> treTypeName = tre.getIdent();
+ DataverseName activeDataverse = treTypeName.first == null ? defaultDataverse : treTypeName.first;
+ return new TypeSignature(activeDataverse, treTypeName.second.getValue());
+ }
}
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 0cc49ba..6e1db20 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
@@ -18,13 +18,12 @@
*/
package org.apache.asterix.app.translator;
-import static org.apache.asterix.common.functions.FunctionConstants.ASTERIX_DV;
-
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
@@ -39,6 +38,7 @@
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutorService;
+import java.util.stream.Collectors;
import org.apache.asterix.active.ActivityState;
import org.apache.asterix.active.EntityId;
@@ -97,10 +97,6 @@
import org.apache.asterix.lang.common.base.IStatementRewriter;
import org.apache.asterix.lang.common.base.Statement;
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;
-import org.apache.asterix.lang.common.expression.UnorderedListTypeDefinition;
import org.apache.asterix.lang.common.statement.CompactStatement;
import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
import org.apache.asterix.lang.common.statement.CreateAdapterStatement;
@@ -173,6 +169,7 @@
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;
@@ -930,8 +927,8 @@
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
"Typed open index can only be created on the record part");
}
- Map<TypeSignature, IAType> typeMap =
- TypeTranslator.computeTypes(mdTxnCtx, fieldExpr.second.getType(), indexName, dataverseName);
+ Map<TypeSignature, IAType> typeMap = TypeTranslator.computeTypes(dataverseName, indexName,
+ fieldExpr.second.getType(), dataverseName, mdTxnCtx);
TypeSignature typeSignature = new TypeSignature(dataverseName, indexName);
fieldType = typeMap.get(typeSignature);
overridesFieldTypes = true;
@@ -1265,8 +1262,8 @@
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
"Cannot redefine builtin type " + typeName + ".");
} else {
- Map<TypeSignature, IAType> typeMap = TypeTranslator.computeTypes(mdTxnCtx,
- stmtCreateType.getTypeDef(), stmtCreateType.getIdent().getValue(), dataverseName);
+ Map<TypeSignature, IAType> typeMap = TypeTranslator.computeTypes(dataverseName,
+ stmtCreateType.getIdent().getValue(), stmtCreateType.getTypeDef(), dataverseName, mdTxnCtx);
TypeSignature typeSignature = new TypeSignature(dataverseName, typeName);
IAType type = typeMap.get(typeSignature);
MetadataManager.INSTANCE.addDatatype(mdTxnCtx, new Datatype(dataverseName, typeName, type, false));
@@ -1764,29 +1761,6 @@
}
}
- private static Pair<DataverseName, String> extractTypeName(TypeExpression typ, DataverseName activeDataverse) {
- String typeName;
- DataverseName typeDv = ASTERIX_DV;
- switch (typ.getTypeKind()) {
- case ORDEREDLIST:
- return extractTypeName(((OrderedListTypeDefinition) typ).getItemTypeExpression(), activeDataverse);
- case UNORDEREDLIST:
- return extractTypeName(((UnorderedListTypeDefinition) typ).getItemTypeExpression(), activeDataverse);
- case RECORD:
- break;
- case TYPEREFERENCE:
- TypeReferenceExpression typeRef = ((TypeReferenceExpression) typ);
- typeName = typeRef.getIdent().getSecond().toString();
- if (typeRef.getIdent().getFirst() != null) {
- typeDv = typeRef.getIdent().getFirst();
- } else if (BuiltinTypeMap.getBuiltinType(typeName) == null) {
- typeDv = activeDataverse;
- }
- return new Pair<>(typeDv, typeName);
- }
- return null;
- }
-
protected void handleCreateFunctionStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
CreateFunctionStatement cfs = (CreateFunctionStatement) stmt;
SourceLocation sourceLoc = cfs.getSourceLocation();
@@ -1804,51 +1778,64 @@
if (dv == null) {
throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverseName);
}
- List<String> argNames = new ArrayList<>();
- List<Pair<DataverseName, IAType>> argType = new ArrayList<>();
- List<VarIdentifier> paramVars = new ArrayList<>();
- List<Pair<DataverseName, String>> dependentTypes = new ArrayList<>();
- for (Pair<VarIdentifier, IndexedTypeExpression> var : cfs.getArgs()) {
- if (var.getSecond() != null) {
- Pair<DataverseName, String> baseType = extractTypeName(var.second.getType(), dataverseName);
- Map<TypeSignature, IAType> typeMap = TypeTranslator.computeTypes(mdTxnCtx, var.second.getType(),
- var.first.getValue(), dataverseName);
- IAType t = typeMap.values().iterator().next();
- if (typeMap.size() <= 0) {
- throw new CompilationException(ErrorCode.UNKNOWN_TYPE, sourceLoc,
- var.second.getType().toString());
- }
- if (!ASTERIX_DV.equals(baseType.getFirst())) {
- dependentTypes.add(baseType);
- }
- argType.add(new Pair<>(baseType.first, t));
- paramVars.add(var.getFirst());
- argNames.add(var.getFirst().getValue());
+ 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 {
- paramVars.add(var.getFirst());
- argType.add(new Pair<>(ASTERIX_DV, BuiltinType.ANY));
- argNames.add(var.getFirst().getValue());
+ 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);
+ }
}
+ paramVars.add(argVar);
+ argNames.add(argVar.getValue());
+ argTypes.add(argType);
}
- IndexedTypeExpression ret = cfs.getReturnType();
- Pair<DataverseName, IAType> retType;
- if (ret != null) {
- Pair<DataverseName, String> baseType = extractTypeName(ret.getType(), dataverseName);
- Map<TypeSignature, IAType> typeMap =
- TypeTranslator.computeTypes(mdTxnCtx, ret.getType(), "return", dataverseName);
- IAType t = typeMap.values().iterator().next();
- if (typeMap.size() <= 0) {
- throw new CompilationException(ErrorCode.UNKNOWN_TYPE, sourceLoc, ret.getType().toString());
- }
- if (!ASTERIX_DV.equals(baseType.getFirst())) {
- dependentTypes.add(baseType);
- }
- retType = new Pair<>(baseType.first, t);
+ IndexedTypeExpression returnTypeExpr = cfs.getReturnType();
+ IAType returnType;
+ if (returnTypeExpr == null) {
+ returnType = BuiltinType.ANY;
} else {
- retType = new Pair<>(ASTERIX_DV, BuiltinType.ANY);
+ 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);
+ }
}
if (cfs.isExternal()) {
+ Function.FunctionLanguage functionLang = Function.FunctionLanguage.findByName(cfs.getLang());
+ if (functionLang == null || !functionLang.isExternal()) {
+ String expectedExternalLanguages = Arrays.stream(Function.FunctionLanguage.values())
+ .filter(Function.FunctionLanguage::isExternal).map(Function.FunctionLanguage::getName)
+ .collect(Collectors.joining(" or "));
+ throw new CompilationException(ErrorCode.COMPILATION_INCOMPATIBLE_FUNCTION_LANGUAGE, sourceLoc,
+ expectedExternalLanguages, cfs.getLang());
+ }
Library libraryInMetadata = MetadataManager.INSTANCE.getLibrary(mdTxnCtx, dataverseName, libraryName);
if (libraryInMetadata == null) {
throw new CompilationException(ErrorCode.UNKNOWN_LIBRARY, sourceLoc, libraryName);
@@ -1856,9 +1843,9 @@
// Add functions
List<List<Triple<DataverseName, String, String>>> dependencies =
FunctionUtil.getExternalFunctionDependencies(dependentTypes);
- Function f = new Function(signature, argType, argNames, retType, cfs.getExternalIdent(), cfs.getLang(),
- cfs.isUnknownable(), cfs.isNullCall(), cfs.isDeterministic(), libraryName,
- FunctionKind.SCALAR.toString(), dependencies, cfs.getResources());
+ Function f = new Function(signature, argNames, argTypes, returnType, cfs.getExternalIdentifier(),
+ FunctionKind.SCALAR.toString(), functionLang, libraryName, cfs.getNullCall(),
+ cfs.getDeterministic(), cfs.getResources(), dependencies);
MetadataManager.INSTANCE.addFunction(mdTxnCtx, f);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Installed function: " + signature);
@@ -1876,9 +1863,8 @@
List<List<Triple<DataverseName, String, String>>> dependencies =
FunctionUtil.getFunctionDependencies(rewriterFactory.createQueryRewriter(),
cfs.getFunctionBodyExpression(), metadataProvider, dependentTypes);
- Function function = new Function(signature, argType, argNames, retType, cfs.getFunctionBody(),
- getFunctionLanguage(), cfs.isUnknownable(), cfs.isNullCall(), cfs.isDeterministic(), null,
- FunctionKind.SCALAR.toString(), dependencies, null);
+ Function function = new Function(signature, argNames, argTypes, returnType, cfs.getFunctionBody(),
+ FunctionKind.SCALAR.toString(), getFunctionLanguage(), null, null, null, null, dependencies);
MetadataManager.INSTANCE.addFunction(mdTxnCtx, function);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Installed function: " + signature);
@@ -1895,6 +1881,21 @@
}
}
+ 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);
+ }
+ return type;
+ }
+
+ private static String createFunctionTypeNamePrefix(String name, int arity) {
+ return "fn$" + name + "$" + arity;
+ }
+
protected void handleCreateAdapterStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
CreateAdapterStatement cas = (CreateAdapterStatement) stmt;
SourceLocation sourceLoc = cas.getSourceLocation();
@@ -1934,12 +1935,12 @@
}
}
- private String getFunctionLanguage() {
+ private Function.FunctionLanguage getFunctionLanguage() {
switch (compilationProvider.getLanguage()) {
case SQLPP:
- return Function.LANGUAGE_SQLPP;
+ return Function.FunctionLanguage.SQLPP;
case AQL:
- return Function.LANGUAGE_AQL;
+ return Function.FunctionLanguage.AQL;
default:
throw new IllegalStateException(String.valueOf(compilationProvider.getLanguage()));
}
diff --git a/asterixdb/asterix-app/src/test/resources/metadata/results/basic/meta06/meta06.1.adm b/asterixdb/asterix-app/src/test/resources/metadata/results/basic/meta06/meta06.1.adm
index 1ebef3e..9df885d 100644
--- a/asterixdb/asterix-app/src/test/resources/metadata/results/basic/meta06/meta06.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/metadata/results/basic/meta06/meta06.1.adm
@@ -1 +1 @@
-{ "DataverseName": "testdv", "Name": "fun01", "Arity": "0", "Params": [ ], "ReturnType": "asterix.any", "Definition": "\"This is an AQL Bodied UDF\"", "Language": "AQL", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ArgTypes": [ ], "WithParams": [ ], "Unknownable": "true", "NullCall": "false", "Deterministic": "false" }
+{ "DataverseName": "testdv", "Name": "fun01", "Arity": "0", "Params": [ ], "ReturnType": "any", "Definition": "\"This is an AQL Bodied UDF\"", "Language": "AQL", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ ] }
\ 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
new file mode 100644
index 0000000..5a5bbec
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.0.ddl.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+DROP DATAVERSE externallibtest if exists;
+CREATE DATAVERSE externallibtest;
+USE externallibtest;
+
+create type CountryCapitalType if not exists as closed {
+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
new file mode 100644
index 0000000..d1e0e87
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.1.lib.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+install externallibtest testlib target/data/externallib/asterix-external-data-testlib.zip
\ No newline at end of file
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
new file mode 100644
index 0000000..2826b9e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.2.ddl.sqlpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+use externallibtest;
+
+create function myfn001()
+ language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
+
+create function myfn002(a)
+ language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
+
+create function myfn003(a:string, b:[bigint], c:{{boolean}})
+ returns string
+ language java as "testlib","org.apache.asterix.external.library.CapitalFinderFactory";
+
+create function myfn004(a:CountryCapitalType, b:[CountryCapitalType])
+ 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?
+ 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}}?
+ 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";
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
new file mode 100644
index 0000000..b099f5f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.3.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+SELECT object_remove(fn, "Timestamp") as fn
+FROM Metadata.`Function` fn
+WHERE fn.DataverseName = "externallibtest"
+UNION ALL
+SELECT object_remove(dt, "Timestamp") as dt
+FROM Metadata.`Datatype` dt
+WHERE dt.DataverseName = "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.lib.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.4.lib.sqlpp
new file mode 100644
index 0000000..86af80f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.4.lib.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+uninstall externallibtest testlib
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.5.ddl.sqlpp
new file mode 100644
index 0000000..cb57494
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/udf_metadata/udf_metadata.5.ddl.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+DROP DATAVERSE externallibtest;
\ 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
new file mode 100644
index 0000000..9f268d1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.1.ddl.sqlpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create type MyType1 as {
+ `id`: int,
+ `value`: string
+};
+
+create function myfn001() {
+ 42
+};
+
+create function myfn002(a) {
+ 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
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.2.query.sqlpp
new file mode 100644
index 0000000..bef3e8e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf32_metadata/udf32_metadata.2.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+SELECT object_remove(fn, "Timestamp") as fn
+FROM Metadata.`Function` fn
+WHERE fn.DataverseName = "test"
+UNION ALL
+SELECT object_remove(dt, "Timestamp") as dt
+FROM Metadata.`Datatype` dt
+WHERE dt.DataverseName = "test"
+ORDER BY dt.DatatypeName, fn.Name;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/cross-dataverse/cross-dv15/cross-dv15.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/cross-dataverse/cross-dv15/cross-dv15.1.adm
index bef1653..ed83617 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/cross-dataverse/cross-dv15/cross-dv15.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/cross-dataverse/cross-dv15/cross-dv15.1.adm
@@ -1,3 +1,3 @@
-{ "DataverseName": "testdv1", "Name": "fun01", "Arity": "0", "ReturnType": "asterix.any" }
-{ "DataverseName": "testdv1", "Name": "fun02", "Arity": "1", "ReturnType": "asterix.any" }
-{ "DataverseName": "testdv1", "Name": "fun03", "Arity": "2", "ReturnType": "asterix.any" }
+{ "DataverseName": "testdv1", "Name": "fun01", "Arity": "0", "ReturnType": "any" }
+{ "DataverseName": "testdv1", "Name": "fun02", "Arity": "1", "ReturnType": "any" }
+{ "DataverseName": "testdv1", "Name": "fun03", "Arity": "2", "ReturnType": "any" }
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
new file mode 100644
index 0000000..e0d43e1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm
@@ -0,0 +1,23 @@
+{ "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 } }
+{ "dt": { "DataverseName": "externallibtest", "DatatypeName": "CountryCapitalType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "Record": { "IsOpen": false, "Fields": [ { "FieldName": "country", "FieldType": "string", "IsNullable": false }, { "FieldName": "capital", "FieldType": "string", "IsNullable": 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" } } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/single-line-definition/single-line-definition.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/single-line-definition/single-line-definition.1.adm
index eb11719..10c6384 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/single-line-definition/single-line-definition.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/single-line-definition/single-line-definition.1.adm
@@ -1 +1 @@
-{ "DataverseName": "test", "Name": "printName", "Arity": "0", "ReturnType": "asterix.any", "Definition": "'AsterixDB Shared nothing parallel BDMS'" }
\ No newline at end of file
+{ "DataverseName": "test", "Name": "printName", "Arity": "0", "ReturnType": "any", "Definition": "'AsterixDB Shared nothing parallel BDMS'" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf28/udf28.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf28/udf28.1.adm
index 7397467..07e4942 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf28/udf28.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf28/udf28.1.adm
@@ -1 +1 @@
-{ "DataverseName": "test", "Name": "f1", "Arity": "0", "ReturnType": "asterix.any", "Definition": "100" }
\ No newline at end of file
+{ "DataverseName": "test", "Name": "f1", "Arity": "0", "ReturnType": "any", "Definition": "100" }
\ No newline at end of file
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
new file mode 100644
index 0000000..e181e6a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf32_metadata/udf32_metadata.2.adm
@@ -0,0 +1,23 @@
+{ "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 }, { "FieldName": "value", "FieldType": "string", "IsNullable": 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" } } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml
index bea9ef1..532b8e8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml
@@ -50,6 +50,11 @@
</compilation-unit>
</test-case>
<test-case FilePath="external-library">
+ <compilation-unit name="udf_metadata">
+ <output-dir compare="Text">udf_metadata</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-library">
<compilation-unit name="upperCase">
<output-dir compare="Text">upperCase</output-dir>
</compilation-unit>
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 ae82628..2045fb8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -11805,6 +11805,11 @@
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
+ <compilation-unit name="udf32_metadata">
+ <output-dir compare="Text">udf32_metadata</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="user-defined-functions">
<compilation-unit name="f01">
<output-dir compare="Text">f01</output-dir>
<expected-error>function test.tinyint@0 is not defined</expected-error>
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
index b3097dc..a6fde0c 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
@@ -67,7 +67,7 @@
AqlQueryRewriter(IParserFactory parserFactory) {
this.parserFactory = parserFactory;
- functionParser = new FunctionParser(Function.LANGUAGE_AQL, this.parserFactory);
+ functionParser = new FunctionParser(Function.FunctionLanguage.AQL, this.parserFactory);
}
private void setup(List<FunctionDecl> declaredFunctions, IReturningStatement topStatement,
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 0bd1f84..2e8754c 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
@@ -35,11 +35,11 @@
public class FunctionParser {
- private final String language;
+ private final Function.FunctionLanguage language;
private final IParserFactory parserFactory;
- public FunctionParser(String language, IParserFactory parserFactory) {
+ public FunctionParser(Function.FunctionLanguage language, IParserFactory parserFactory) {
this.language = language;
this.parserFactory = parserFactory;
}
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 d7819e0..1c21665 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
@@ -42,19 +42,15 @@
private final String functionBody;
private final Expression functionBodyExpression;
private final boolean ifNotExists;
+ private final List<Pair<VarIdentifier, IndexedTypeExpression>> args;
+ private final IndexedTypeExpression returnType;
- IndexedTypeExpression returnType;
- boolean deterministic;
- boolean nullCall;
- String lang;
- String libName;
- String externalIdent;
- List<Pair<VarIdentifier, IndexedTypeExpression>> args;
- AdmObjectNode resources;
-
- public String getFunctionBody() {
- return functionBody;
- }
+ private final String lang;
+ private final String libName;
+ private final String externalIdentifier;
+ private final Boolean deterministic;
+ private final Boolean nullCall;
+ private final AdmObjectNode resources;
public CreateFunctionStatement(FunctionSignature signature,
List<Pair<VarIdentifier, IndexedTypeExpression>> parameterList, IndexedTypeExpression returnType,
@@ -65,25 +61,30 @@
this.ifNotExists = ifNotExists;
this.args = parameterList;
this.returnType = returnType;
+ this.lang = null;
+ this.libName = null;
+ this.externalIdentifier = null;
+ this.deterministic = null;
+ this.nullCall = null;
+ this.resources = null;
}
public CreateFunctionStatement(FunctionSignature signature,
List<Pair<VarIdentifier, IndexedTypeExpression>> parameterList, IndexedTypeExpression returnType,
- boolean deterministic, boolean nullCall, String lang, String libName, String externalIdent,
+ boolean deterministic, boolean nullCall, String lang, String libName, String externalIdentifier,
RecordConstructor resources, boolean ifNotExists) throws CompilationException {
this.signature = signature;
+ this.ifNotExists = ifNotExists;
this.args = parameterList;
this.returnType = returnType;
this.deterministic = deterministic;
this.nullCall = nullCall;
this.lang = lang;
this.libName = libName;
- this.externalIdent = externalIdent;
+ this.externalIdentifier = externalIdentifier;
this.resources = resources == null ? null : ExpressionUtils.toNode(resources);
- functionBody = null;
- this.ifNotExists = ifNotExists;
+ this.functionBody = null;
this.functionBodyExpression = null;
-
}
public boolean getIfNotExists() {
@@ -99,48 +100,48 @@
return signature;
}
+ public String getFunctionBody() {
+ return functionBody;
+ }
+
public Expression getFunctionBodyExpression() {
return functionBodyExpression;
}
- public IndexedTypeExpression getReturnType() {
- return returnType;
- }
-
- public boolean isDeterministic() {
- return deterministic;
- }
-
- public boolean isNullCall() {
- return nullCall;
- }
-
- public boolean isExternal() {
- return externalIdent != null;
- }
-
- public boolean isUnknownable() {
- return returnType == null || returnType.isUnknownable();
- }
-
- public String getLang() {
- return lang;
- }
-
- public String getLibName() {
- return libName;
- }
-
- public String getExternalIdent() {
- return externalIdent;
- }
-
public List<Pair<VarIdentifier, IndexedTypeExpression>> getArgs() {
return args;
}
+ public IndexedTypeExpression getReturnType() {
+ return returnType;
+ }
+
+ public boolean isExternal() {
+ return externalIdentifier != null;
+ }
+
+ public String getExternalIdentifier() {
+ return externalIdentifier;
+ }
+
+ public String getLibName() {
+ return libName;
+ }
+
+ public String getLang() {
+ return lang;
+ }
+
+ public Boolean getDeterministic() {
+ return deterministic;
+ }
+
+ public Boolean getNullCall() {
+ return nullCall;
+ }
+
public Map<String, String> getResources() throws CompilationException {
- return resources != null ? ConfigurationUtil.toProperties(resources) : Collections.EMPTY_MAP;
+ return resources != null ? ConfigurationUtil.toProperties(resources) : Collections.emptyMap();
}
@Override
@@ -152,5 +153,4 @@
public byte getCategory() {
return Category.DDL;
}
-
}
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 f803af9..5308b96 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,7 +19,10 @@
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.List;
import java.util.Objects;
import java.util.Set;
@@ -32,10 +35,16 @@
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;
+import org.apache.asterix.lang.common.expression.UnorderedListTypeDefinition;
import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.metadata.MetadataManager;
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.functions.BuiltinFunctions;
import org.apache.asterix.om.utils.ConstantExpressionUtil;
@@ -75,6 +84,34 @@
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,
+ DataverseName defaultDataverse) {
+ switch (typeExpr.getTypeKind()) {
+ case ORDEREDLIST:
+ return extractNestedTypeName(((OrderedListTypeDefinition) typeExpr).getItemTypeExpression(),
+ defaultDataverse);
+ case UNORDEREDLIST:
+ return extractNestedTypeName(((UnorderedListTypeDefinition) typeExpr).getItemTypeExpression(),
+ defaultDataverse);
+ case RECORD:
+ break;
+ 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);
+ }
+ return null;
+ }
+
@FunctionalInterface
public interface IFunctionCollector {
Set<CallExpr> getFunctionCalls(Expression expression) throws CompilationException;
@@ -167,8 +204,7 @@
messageBuilder.toString());
}
- if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_AQL)
- || function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_SQLPP)) {
+ if (!function.getLanguage().isExternal()) {
FunctionDecl functionDecl = functionParser.getFunctionDecl(function);
if (functionDecl != null) {
if (functionDecls.contains(functionDecl)) {
@@ -186,7 +222,7 @@
}
public static List<List<Triple<DataverseName, String, String>>> getFunctionDependencies(IQueryRewriter rewriter,
- Expression expression, MetadataProvider metadataProvider, List<Pair<DataverseName, String>> argTypes)
+ Expression expression, MetadataProvider metadataProvider, Collection<Pair<DataverseName, String>> argTypes)
throws CompilationException {
Set<CallExpr> functionCalls = rewriter.getFunctionCalls(expression);
//Get the List of used functions and used datasets
@@ -216,7 +252,7 @@
}
public static List<List<Triple<DataverseName, String, String>>> getExternalFunctionDependencies(
- List<Pair<DataverseName, String>> argTypes) {
+ 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<>();
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index ccc4b26..b439ba1 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -101,7 +101,7 @@
public SqlppQueryRewriter(IParserFactory parserFactory) {
this.parserFactory = parserFactory;
- functionRepository = new FunctionParser(Function.LANGUAGE_SQLPP, parserFactory);
+ functionRepository = new FunctionParser(Function.FunctionLanguage.SQLPP, parserFactory);
}
protected void setup(List<FunctionDecl> declaredFunctions, IReturningStatement topExpr,
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataTransactionContext.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataTransactionContext.java
index c72df1f..0de138f 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataTransactionContext.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataTransactionContext.java
@@ -158,8 +158,7 @@
}
public void dropFunction(FunctionSignature signature) {
- Function function =
- new Function(signature, null, null, null, null, null, false, false, false, null, null, null, null);
+ Function function = new Function(signature, null, null, null, null, null, null, null, false, false, null, null);
droppedCache.addFunctionIfNotExists(function);
logAndApply(new MetadataLogicalOperation(function, false));
}
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 2af58e3..cbd02a0 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
@@ -114,8 +114,6 @@
public static final int PROPERTIES_VALUE_FIELD_INDEX = 1;
public static final String PROPERTIES_VALUE_FIELD_NAME = "value";
public static final String TYPE_DV_FIELD_NAME = "Dataverse";
- public static final String TYPE_NAME_FIELD_NAME = "Type";
- public static final String TYPE_UNKNOWNABLE_FIELD_NAME = "Unknownable";
public static final ARecordType POLICY_PARAMS_RECORDTYPE = createPropertiesRecordType();
public static final ARecordType DATASOURCE_ADAPTER_PROPERTIES_RECORDTYPE = createPropertiesRecordType();
public static final ARecordType COMPACTION_POLICY_PROPERTIES_RECORDTYPE = createPropertiesRecordType();
@@ -341,12 +339,12 @@
public static final int FUNCTION_ARECORD_FUNCTION_DEPENDENCIES_FIELD_INDEX = 8;
//open types
public static final String FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME = "WithParams";
- public static final String FUNCTION_ARECORD_FUNCTION_WITHPARAM_TYPE_NAME = "Parameter";
public static final String FUNCTION_ARECORD_FUNCTION_LIBRARY_FIELD_NAME = "Library";
- public static final String FUNCTION_ARECORD_FUNCTION_NULLABILITY_FIELD_NAME = "Unknownable";
+ 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_ARGTYPES_FIELD_NAME = "ArgTypes";
+ public static final String FUNCTION_ARECORD_FUNCTION_PARAMTYPES_FIELD_NAME = "ParamTypes";
+
public static final ARecordType FUNCTION_RECORDTYPE = createRecordType(
// RecordTypeName
RECORD_NAME_FUNCTION,
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 055c788..815cd22 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
@@ -18,10 +18,11 @@
*/
package org.apache.asterix.metadata.entities;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import org.apache.asterix.common.functions.FunctionSignature;
@@ -29,57 +30,42 @@
import org.apache.asterix.metadata.MetadataCache;
import org.apache.asterix.metadata.api.IMetadataEntity;
import org.apache.asterix.om.types.IAType;
-import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.common.utils.Triple;
public class Function implements IMetadataEntity<Function> {
- private static final long serialVersionUID = 2L;
- public static final String LANGUAGE_AQL = "AQL";
- public static final String LANGUAGE_SQLPP = "SQLPP";
- public static final String LANGUAGE_JAVA = "JAVA";
- public static final String LANGUAGE_PYTHON = "PYTHON";
+ private static final long serialVersionUID = 3L;
private final FunctionSignature signature;
- private final List<List<Triple<DataverseName, String, String>>> dependencies;
- private final List<Pair<DataverseName, IAType>> arguments;
- private final String body;
- private final Pair<DataverseName, IAType> returnType;
private final List<String> argNames;
- private final String language;
+ private final List<IAType> argTypes;
+ private final IAType returnType;
+ private final String body;
+ private final FunctionLanguage language;
private final String kind;
private final String library;
- private final boolean nullable;
+ 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 boolean deterministic;
- private final boolean nullCall;
+ private final List<List<Triple<DataverseName, String, String>>> dependencies;
- public Function(FunctionSignature signature, List<Pair<DataverseName, IAType>> arguments, List<String> argNames,
- Pair<DataverseName, IAType> returnType, String functionBody, String language, boolean unknownable,
- boolean nullCall, boolean deterministic, String library, String functionKind,
- List<List<Triple<DataverseName, String, String>>> dependencies, Map<String, String> params) {
+ public Function(FunctionSignature signature, List<String> argNames, List<IAType> argTypes, IAType returnType,
+ String functionBody, String functionKind, FunctionLanguage language, String library, Boolean nullCall,
+ Boolean deterministic, Map<String, String> params,
+ List<List<Triple<DataverseName, String, String>>> dependencies) {
this.signature = signature;
- this.arguments = arguments;
this.argNames = argNames;
+ this.argTypes = argTypes;
this.body = functionBody;
this.returnType = returnType;
this.language = language;
- this.nullable = unknownable;
this.kind = functionKind;
this.library = library;
- if (dependencies == null) {
- this.dependencies = new ArrayList<>(2);
- this.dependencies.add(Collections.emptyList());
- this.dependencies.add(Collections.emptyList());
- } else {
- this.dependencies = dependencies;
- }
- if (params == null) {
- this.params = new HashMap<>();
- } else {
- this.params = params;
- }
this.nullCall = nullCall;
this.deterministic = deterministic;
+ this.params = params == null ? new HashMap<>() : params;
+ this.dependencies = dependencies == null
+ ? Arrays.asList(Collections.emptyList(), Collections.emptyList(), Collections.emptyList())
+ : dependencies;
}
public FunctionSignature getSignature() {
@@ -98,42 +84,26 @@
return signature.getArity();
}
- public List<Pair<DataverseName, IAType>> getArguments() {
- return arguments;
- }
-
public List<String> getArgNames() {
return argNames;
}
- public List<List<Triple<DataverseName, String, String>>> getDependencies() {
- return dependencies;
+ public List<IAType> getArgTypes() {
+ return argTypes;
}
public String getFunctionBody() {
return body;
}
- public Pair<DataverseName, IAType> getReturnType() {
+ public IAType getReturnType() {
return returnType;
}
- public String getLanguage() {
+ public FunctionLanguage getLanguage() {
return language;
}
- public boolean isUnknownable() {
- return nullable;
- }
-
- public boolean isNullCall() {
- return nullCall;
- }
-
- public boolean isDeterministic() {
- return deterministic;
- }
-
public String getKind() {
return kind;
}
@@ -142,10 +112,22 @@
return library;
}
+ public Boolean getNullCall() {
+ return nullCall;
+ }
+
+ public Boolean getDeterministic() {
+ return deterministic;
+ }
+
public Map<String, String> getParams() {
return params;
}
+ public List<List<Triple<DataverseName, String, String>>> getDependencies() {
+ return dependencies;
+ }
+
@Override
public Function addToCache(MetadataCache cache) {
return cache.addFunctionIfNotExists(this);
@@ -156,4 +138,30 @@
return cache.dropFunction(this);
}
+ public enum FunctionLanguage {
+ // WARNING: do not change these language names because
+ // these values are stored in function metadata
+ AQL(false),
+ SQLPP(false),
+ JAVA(true),
+ PYTHON(true);
+
+ private final boolean isExternal;
+
+ FunctionLanguage(boolean isExternal) {
+ this.isExternal = isExternal;
+ }
+
+ public boolean isExternal() {
+ return isExternal;
+ }
+
+ public String getName() {
+ return name();
+ }
+
+ public static FunctionLanguage findByName(String name) {
+ return FunctionLanguage.valueOf(name.toUpperCase(Locale.ROOT));
+ }
+ }
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/AbstractDatatypeTupleTranslator.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/AbstractDatatypeTupleTranslator.java
new file mode 100644
index 0000000..7a37597
--- /dev/null
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/AbstractDatatypeTupleTranslator.java
@@ -0,0 +1,216 @@
+/*
+ * 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.entitytupletranslators;
+
+import java.io.DataOutput;
+
+import org.apache.asterix.builders.IARecordBuilder;
+import org.apache.asterix.builders.OrderedListBuilder;
+import org.apache.asterix.builders.RecordBuilder;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.common.transactions.TxnId;
+import org.apache.asterix.metadata.MetadataNode;
+import org.apache.asterix.metadata.api.IMetadataIndex;
+import org.apache.asterix.metadata.bootstrap.MetadataRecordTypes;
+import org.apache.asterix.metadata.entities.Datatype;
+import org.apache.asterix.om.base.ABoolean;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AbstractCollectionType;
+import org.apache.asterix.om.types.AbstractComplexType;
+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.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+
+public abstract class AbstractDatatypeTupleTranslator<T> extends AbstractTupleTranslator<T> {
+
+ public enum DerivedTypeTag {
+ RECORD,
+ UNORDEREDLIST,
+ ORDEREDLIST
+ }
+
+ protected final MetadataNode metadataNode;
+
+ protected final TxnId txnId;
+
+ public AbstractDatatypeTupleTranslator(TxnId txnId, MetadataNode metadataNode, boolean getTuple,
+ IMetadataIndex metadataIndex, int payloadTupleFieldIndex) {
+ super(getTuple, metadataIndex, payloadTupleFieldIndex);
+ this.txnId = txnId;
+ this.metadataNode = metadataNode;
+ }
+
+ protected void writeDerivedTypeRecord(DataverseName dataverseName, AbstractComplexType derivedDatatype,
+ DataOutput out, boolean isAnonymous) throws HyracksDataException {
+ DerivedTypeTag tag;
+ IARecordBuilder derivedRecordBuilder = new RecordBuilder();
+ ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
+ switch (derivedDatatype.getTypeTag()) {
+ case ARRAY:
+ tag = DerivedTypeTag.ORDEREDLIST;
+ break;
+ case MULTISET:
+ tag = DerivedTypeTag.UNORDEREDLIST;
+ break;
+ case OBJECT:
+ tag = DerivedTypeTag.RECORD;
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ "No metadata record Type for " + derivedDatatype.getDisplayName());
+ }
+
+ derivedRecordBuilder.reset(MetadataRecordTypes.DERIVEDTYPE_RECORDTYPE);
+
+ // write field 0
+ fieldValue.reset();
+ aString.setValue(tag.toString());
+ stringSerde.serialize(aString, fieldValue.getDataOutput());
+ derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_TAG_FIELD_INDEX, fieldValue);
+
+ // write field 1
+ fieldValue.reset();
+ booleanSerde.serialize(ABoolean.valueOf(isAnonymous), fieldValue.getDataOutput());
+ derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ISANONYMOUS_FIELD_INDEX, fieldValue);
+
+ switch (tag) {
+ case RECORD:
+ fieldValue.reset();
+ writeRecordType(dataverseName, derivedDatatype, fieldValue.getDataOutput());
+ derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_RECORD_FIELD_INDEX, fieldValue);
+ break;
+ case UNORDEREDLIST:
+ fieldValue.reset();
+ writeCollectionType(dataverseName, derivedDatatype, fieldValue.getDataOutput());
+ derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_UNORDEREDLIST_FIELD_INDEX,
+ fieldValue);
+ break;
+ case ORDEREDLIST:
+ fieldValue.reset();
+ writeCollectionType(dataverseName, derivedDatatype, fieldValue.getDataOutput());
+ derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ORDEREDLIST_FIELD_INDEX,
+ fieldValue);
+ break;
+ }
+ derivedRecordBuilder.write(out, true);
+ }
+
+ private void writeCollectionType(DataverseName dataverseName, AbstractComplexType type, DataOutput out)
+ throws HyracksDataException {
+ AbstractCollectionType listType = (AbstractCollectionType) type;
+ IAType itemType = listType.getItemType();
+ if (itemType.getTypeTag().isDerivedType()) {
+ handleNestedDerivedType(dataverseName, itemType.getTypeName(), (AbstractComplexType) itemType);
+ }
+ aString.setValue(listType.getItemType().getTypeName());
+ stringSerde.serialize(aString, out);
+ }
+
+ private void writeRecordType(DataverseName dataverseName, AbstractComplexType type, DataOutput out)
+ throws HyracksDataException {
+
+ ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
+ ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
+ IARecordBuilder recordRecordBuilder = new RecordBuilder();
+ IARecordBuilder fieldRecordBuilder = new RecordBuilder();
+
+ ARecordType recType = (ARecordType) type;
+ OrderedListBuilder listBuilder = new OrderedListBuilder();
+ listBuilder.reset(new AOrderedListType(MetadataRecordTypes.FIELD_RECORDTYPE, null));
+
+ for (int i = 0, n = recType.getFieldNames().length; i < n; i++) {
+ String fieldName = recType.getFieldNames()[i];
+ IAType fieldType = recType.getFieldTypes()[i];
+
+ boolean fieldIsNullable = false;
+ if (NonTaggedFormatUtil.isOptional(fieldType)) {
+ fieldIsNullable = true;
+ fieldType = ((AUnionType) fieldType).getActualType();
+ }
+ if (fieldType.getTypeTag().isDerivedType()) {
+ handleNestedDerivedType(dataverseName, fieldType.getTypeName(), (AbstractComplexType) fieldType);
+ }
+
+ itemValue.reset();
+
+ fieldRecordBuilder.reset(MetadataRecordTypes.FIELD_RECORDTYPE);
+
+ // write field 0
+ fieldValue.reset();
+ aString.setValue(fieldName);
+ stringSerde.serialize(aString, fieldValue.getDataOutput());
+ fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_FIELDNAME_FIELD_INDEX, fieldValue);
+
+ // write field 1
+ fieldValue.reset();
+ aString.setValue(fieldType.getTypeName());
+ stringSerde.serialize(aString, fieldValue.getDataOutput());
+ fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_FIELDTYPE_FIELD_INDEX, fieldValue);
+
+ // write field 2
+ fieldValue.reset();
+ booleanSerde.serialize(ABoolean.valueOf(fieldIsNullable), fieldValue.getDataOutput());
+ fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_ISNULLABLE_FIELD_INDEX, fieldValue);
+
+ // write record
+ fieldRecordBuilder.write(itemValue.getDataOutput(), true);
+
+ // add item to the list of fields
+ listBuilder.addItem(itemValue);
+ }
+
+ recordRecordBuilder.reset(MetadataRecordTypes.RECORD_RECORDTYPE);
+ // write field 0
+ fieldValue.reset();
+ booleanSerde.serialize(ABoolean.valueOf(recType.isOpen()), fieldValue.getDataOutput());
+ recordRecordBuilder.addField(MetadataRecordTypes.RECORDTYPE_ARECORD_ISOPEN_FIELD_INDEX, fieldValue);
+
+ // write field 1
+ fieldValue.reset();
+ listBuilder.write(fieldValue.getDataOutput(), true);
+ recordRecordBuilder.addField(MetadataRecordTypes.RECORDTYPE_ARECORD_FIELDS_FIELD_INDEX, fieldValue);
+
+ // write record
+ recordRecordBuilder.write(out, true);
+ }
+
+ protected void handleNestedDerivedType(DataverseName dataverseName, String typeName, AbstractComplexType nestedType)
+ throws HyracksDataException {
+ try {
+ metadataNode.addDatatype(txnId, new Datatype(dataverseName, typeName, nestedType, true));
+ } catch (AlgebricksException e) {
+ // The nested record type may have been inserted by a previous DDL statement or
+ // by a previous nested type.
+ if (!(e.getCause() instanceof HyracksDataException)) {
+ throw HyracksDataException.create(e);
+ } else {
+ HyracksDataException hde = (HyracksDataException) e.getCause();
+ if (!hde.getComponent().equals(ErrorCode.HYRACKS) || hde.getErrorCode() != ErrorCode.DUPLICATE_KEY) {
+ throw hde;
+ }
+ }
+ }
+ }
+}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatatypeTupleTranslator.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatatypeTupleTranslator.java
index 5009f98..c77f8b6 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatatypeTupleTranslator.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatatypeTupleTranslator.java
@@ -19,12 +19,8 @@
package org.apache.asterix.metadata.entitytupletranslators;
-import java.io.DataOutput;
import java.util.Calendar;
-import org.apache.asterix.builders.IARecordBuilder;
-import org.apache.asterix.builders.OrderedListBuilder;
-import org.apache.asterix.builders.RecordBuilder;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.common.transactions.TxnId;
import org.apache.asterix.metadata.MetadataNode;
@@ -42,37 +38,23 @@
import org.apache.asterix.om.types.ATypeTag;
import org.apache.asterix.om.types.AUnionType;
import org.apache.asterix.om.types.AUnorderedListType;
-import org.apache.asterix.om.types.AbstractCollectionType;
import org.apache.asterix.om.types.AbstractComplexType;
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.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
/**
* Translates a Datatype metadata entity to an ITupleReference and vice versa.
*/
-public class DatatypeTupleTranslator extends AbstractTupleTranslator<Datatype> {
+public class DatatypeTupleTranslator extends AbstractDatatypeTupleTranslator<Datatype> {
// Payload field containing serialized Datatype.
private static final int DATATYPE_PAYLOAD_TUPLE_FIELD_INDEX = 2;
- public enum DerivedTypeTag {
- RECORD,
- UNORDEREDLIST,
- ORDEREDLIST
- }
-
- protected final MetadataNode metadataNode;
- protected final TxnId txnId;
-
protected DatatypeTupleTranslator(TxnId txnId, MetadataNode metadataNode, boolean getTuple) {
- super(getTuple, MetadataPrimaryIndexes.DATATYPE_DATASET, DATATYPE_PAYLOAD_TUPLE_FIELD_INDEX);
- this.txnId = txnId;
- this.metadataNode = metadataNode;
+ super(txnId, metadataNode, getTuple, MetadataPrimaryIndexes.DATATYPE_DATASET,
+ DATATYPE_PAYLOAD_TUPLE_FIELD_INDEX);
}
@Override
@@ -187,7 +169,8 @@
// write field 3
if (fieldType.getTypeTag().isDerivedType()) {
fieldValue.reset();
- writeDerivedTypeRecord(dataType, (AbstractComplexType) fieldType, fieldValue.getDataOutput());
+ writeDerivedTypeRecord(dataType.getDataverseName(), (AbstractComplexType) fieldType,
+ fieldValue.getDataOutput(), dataType.getIsAnonymous());
recordBuilder.addField(MetadataRecordTypes.DATATYPE_ARECORD_DERIVED_FIELD_INDEX, fieldValue);
}
@@ -204,158 +187,4 @@
tuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
return tuple;
}
-
- private void writeDerivedTypeRecord(Datatype type, AbstractComplexType derivedDatatype, DataOutput out)
- throws HyracksDataException {
- DerivedTypeTag tag;
- IARecordBuilder derivedRecordBuilder = new RecordBuilder();
- ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
- switch (derivedDatatype.getTypeTag()) {
- case ARRAY:
- tag = DerivedTypeTag.ORDEREDLIST;
- break;
- case MULTISET:
- tag = DerivedTypeTag.UNORDEREDLIST;
- break;
- case OBJECT:
- tag = DerivedTypeTag.RECORD;
- break;
- default:
- throw new UnsupportedOperationException(
- "No metadata record Type for " + derivedDatatype.getDisplayName());
- }
-
- derivedRecordBuilder.reset(MetadataRecordTypes.DERIVEDTYPE_RECORDTYPE);
-
- // write field 0
- fieldValue.reset();
- aString.setValue(tag.toString());
- stringSerde.serialize(aString, fieldValue.getDataOutput());
- derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_TAG_FIELD_INDEX, fieldValue);
-
- // write field 1
- fieldValue.reset();
- booleanSerde.serialize(type.getIsAnonymous() ? ABoolean.TRUE : ABoolean.FALSE, fieldValue.getDataOutput());
- derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ISANONYMOUS_FIELD_INDEX, fieldValue);
-
- switch (tag) {
- case RECORD:
- fieldValue.reset();
- writeRecordType(type, derivedDatatype, fieldValue.getDataOutput());
- derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_RECORD_FIELD_INDEX, fieldValue);
- break;
- case UNORDEREDLIST:
- fieldValue.reset();
- writeCollectionType(type, derivedDatatype, fieldValue.getDataOutput());
- derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_UNORDEREDLIST_FIELD_INDEX,
- fieldValue);
- break;
- case ORDEREDLIST:
- fieldValue.reset();
- writeCollectionType(type, derivedDatatype, fieldValue.getDataOutput());
- derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ORDEREDLIST_FIELD_INDEX,
- fieldValue);
- break;
- }
- derivedRecordBuilder.write(out, true);
- }
-
- private void writeCollectionType(Datatype instance, AbstractComplexType type, DataOutput out)
- throws HyracksDataException {
- AbstractCollectionType listType = (AbstractCollectionType) type;
- IAType itemType = listType.getItemType();
- if (itemType.getTypeTag().isDerivedType()) {
- handleNestedDerivedType(itemType.getTypeName(), (AbstractComplexType) itemType, instance,
- instance.getDataverseName(), instance.getDatatypeName());
- }
- aString.setValue(listType.getItemType().getTypeName());
- stringSerde.serialize(aString, out);
- }
-
- private void writeRecordType(Datatype instance, AbstractComplexType type, DataOutput out)
- throws HyracksDataException {
-
- ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
- ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
- IARecordBuilder recordRecordBuilder = new RecordBuilder();
- IARecordBuilder fieldRecordBuilder = new RecordBuilder();
-
- ARecordType recType = (ARecordType) type;
- OrderedListBuilder listBuilder = new OrderedListBuilder();
- listBuilder.reset(new AOrderedListType(MetadataRecordTypes.FIELD_RECORDTYPE, null));
- IAType fieldType;
-
- for (int i = 0; i < recType.getFieldNames().length; i++) {
- fieldType = recType.getFieldTypes()[i];
- boolean fieldIsNullable = false;
- if (NonTaggedFormatUtil.isOptional(fieldType)) {
- fieldIsNullable = true;
- fieldType = ((AUnionType) fieldType).getActualType();
- }
- if (fieldType.getTypeTag().isDerivedType()) {
- handleNestedDerivedType(fieldType.getTypeName(), (AbstractComplexType) fieldType, instance,
- instance.getDataverseName(), instance.getDatatypeName());
- }
-
- itemValue.reset();
- fieldRecordBuilder.reset(MetadataRecordTypes.FIELD_RECORDTYPE);
-
- // write field 0
- fieldValue.reset();
- aString.setValue(recType.getFieldNames()[i]);
- stringSerde.serialize(aString, fieldValue.getDataOutput());
- fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_FIELDNAME_FIELD_INDEX, fieldValue);
-
- // write field 1
- fieldValue.reset();
- aString.setValue(fieldType.getTypeName());
- stringSerde.serialize(aString, fieldValue.getDataOutput());
- fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_FIELDTYPE_FIELD_INDEX, fieldValue);
-
- // write field 2
- fieldValue.reset();
- booleanSerde.serialize(fieldIsNullable ? ABoolean.TRUE : ABoolean.FALSE, fieldValue.getDataOutput());
- fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_ISNULLABLE_FIELD_INDEX, fieldValue);
-
- // write record
- fieldRecordBuilder.write(itemValue.getDataOutput(), true);
-
- // add item to the list of fields
- listBuilder.addItem(itemValue);
- }
-
- recordRecordBuilder.reset(MetadataRecordTypes.RECORD_RECORDTYPE);
- // write field 0
- fieldValue.reset();
- booleanSerde.serialize(recType.isOpen() ? ABoolean.TRUE : ABoolean.FALSE, fieldValue.getDataOutput());
- recordRecordBuilder.addField(MetadataRecordTypes.RECORDTYPE_ARECORD_ISOPEN_FIELD_INDEX, fieldValue);
-
- // write field 1
- fieldValue.reset();
- listBuilder.write(fieldValue.getDataOutput(), true);
- recordRecordBuilder.addField(MetadataRecordTypes.RECORDTYPE_ARECORD_FIELDS_FIELD_INDEX, fieldValue);
-
- // write record
- recordRecordBuilder.write(out, true);
- }
-
- private String handleNestedDerivedType(String typeName, AbstractComplexType nestedType, Datatype topLevelType,
- DataverseName dataverseName, String datatypeName) throws HyracksDataException {
- try {
- metadataNode.addDatatype(txnId, new Datatype(dataverseName, typeName, nestedType, true));
- } catch (AlgebricksException e) {
- // The nested record type may have been inserted by a previous DDL statement or
- // by
- // a previous nested type.
- if (!(e.getCause() instanceof HyracksDataException)) {
- throw HyracksDataException.create(e);
- } else {
- HyracksDataException hde = (HyracksDataException) e.getCause();
- if (!hde.getComponent().equals(ErrorCode.HYRACKS) || hde.getErrorCode() != ErrorCode.DUPLICATE_KEY) {
- throw hde;
- }
- }
- }
- return typeName;
- }
}
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 7f4845c..671fb46 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,17 +19,18 @@
package org.apache.asterix.metadata.entitytupletranslators;
-import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_ARGTYPES_FIELD_NAME;
+import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_IS_NULLABLE;
+import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.FIELD_NAME_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_NULLABILITY_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;
-import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.TYPE_DV_FIELD_NAME;
-import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.TYPE_NAME_FIELD_NAME;
-import static org.apache.asterix.metadata.bootstrap.MetadataRecordTypes.TYPE_UNKNOWNABLE_FIELD_NAME;
import java.io.DataOutput;
import java.util.ArrayList;
@@ -43,13 +44,12 @@
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.formats.nontagged.SerializerDeserializerProvider;
import org.apache.asterix.metadata.MetadataNode;
import org.apache.asterix.metadata.bootstrap.MetadataPrimaryIndexes;
import org.apache.asterix.metadata.bootstrap.MetadataRecordTypes;
import org.apache.asterix.metadata.entities.BuiltinTypeMap;
import org.apache.asterix.metadata.entities.Function;
-import org.apache.asterix.om.base.AMutableString;
+import org.apache.asterix.om.base.ABoolean;
import org.apache.asterix.om.base.AOrderedList;
import org.apache.asterix.om.base.ARecord;
import org.apache.asterix.om.base.AString;
@@ -59,12 +59,12 @@
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.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.common.utils.Triple;
-import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
@@ -72,14 +72,11 @@
/**
* Translates a Function metadata entity to an ITupleReference and vice versa.
*/
-public class FunctionTupleTranslator extends AbstractTupleTranslator<Function> {
+public class FunctionTupleTranslator extends AbstractDatatypeTupleTranslator<Function> {
// Payload field containing serialized Function.
private static final int FUNCTION_PAYLOAD_TUPLE_FIELD_INDEX = 3;
- protected final TxnId txnId;
- protected final MetadataNode metadataNode;
-
protected OrderedListBuilder dependenciesListBuilder;
protected OrderedListBuilder dependencyListBuilder;
protected OrderedListBuilder dependencyNameListBuilder;
@@ -88,9 +85,8 @@
protected AOrderedListType listOfLists;
protected FunctionTupleTranslator(TxnId txnId, MetadataNode metadataNode, boolean getTuple) {
- super(getTuple, MetadataPrimaryIndexes.FUNCTION_DATASET, FUNCTION_PAYLOAD_TUPLE_FIELD_INDEX);
- this.txnId = txnId;
- this.metadataNode = metadataNode;
+ super(txnId, metadataNode, getTuple, MetadataPrimaryIndexes.FUNCTION_DATASET,
+ FUNCTION_PAYLOAD_TUPLE_FIELD_INDEX);
if (getTuple) {
dependenciesListBuilder = new OrderedListBuilder();
dependencyListBuilder = new OrderedListBuilder();
@@ -101,116 +97,6 @@
}
}
- private String getFunctionLibrary(ARecord functionRecord) {
- final ARecordType functionType = functionRecord.getType();
- final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_LIBRARY_FIELD_NAME);
- return functionLibraryIdx >= 0 ? ((AString) functionRecord.getValueByPos(functionLibraryIdx)).getStringValue()
- : null;
- }
-
- private boolean getUnknownable(ARecord functionRecord) {
- final ARecordType functionType = functionRecord.getType();
- final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_NULLABILITY_FIELD_NAME);
- return functionLibraryIdx >= 0
- ? Boolean.getBoolean(((AString) functionRecord.getValueByPos(functionLibraryIdx)).getStringValue())
- : false;
- }
-
- private boolean getNullCall(ARecord functionRecord) {
- final ARecordType functionType = functionRecord.getType();
- final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_NULLCALL_FIELD_NAME);
- return functionLibraryIdx >= 0
- ? Boolean.getBoolean(((AString) functionRecord.getValueByPos(functionLibraryIdx)).getStringValue())
- : false;
- }
-
- private boolean getDeterministic(ARecord functionRecord) {
- final ARecordType functionType = functionRecord.getType();
- final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_DETERMINISTIC_FIELD_NAME);
- return functionLibraryIdx >= 0
- ? Boolean.getBoolean(((AString) functionRecord.getValueByPos(functionLibraryIdx)).getStringValue())
- : false;
- }
-
- private Map<String, String> getFunctionWithParams(ARecord functionRecord) {
- String key = "";
- String value = "";
- Map<String, String> adaptorConfiguration = new HashMap<>();
-
- final ARecordType functionType = functionRecord.getType();
- final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME);
- if (functionLibraryIdx >= 0) {
- IACursor cursor = ((AOrderedList) functionRecord.getValueByPos(functionLibraryIdx)).getCursor();
- while (cursor.next()) {
- ARecord field = (ARecord) cursor.get();
- final ARecordType fieldType = field.getType();
- final int keyIdx = fieldType.getFieldIndex(PROPERTIES_NAME_FIELD_NAME);
- if (keyIdx >= 0) {
- key = ((AString) field.getValueByPos(keyIdx)).getStringValue();
- }
- final int valueIdx = fieldType.getFieldIndex(PROPERTIES_VALUE_FIELD_NAME);
- if (valueIdx >= 0) {
- value = ((AString) field.getValueByPos(valueIdx)).getStringValue();
- }
- adaptorConfiguration.put(key, value);
- }
- }
- return adaptorConfiguration;
- }
-
- private Pair<DataverseName, IAType> resolveTypePair(String dvCanonicalForm, String typeName, boolean unknownable)
- throws AlgebricksException {
- DataverseName dvName = DataverseName.createFromCanonicalForm(dvCanonicalForm);
- Pair<DataverseName, IAType> typePair = new Pair<>(null, null);
- typePair.first = dvName;
- if (BuiltinType.ANY.getTypeName().equalsIgnoreCase(typeName)) {
- typePair.second = BuiltinType.ANY;
- } else {
- typePair.second = BuiltinTypeMap.getTypeFromTypeName(metadataNode, txnId, dvName, typeName, unknownable);
- }
- return typePair;
- }
-
- private List<Pair<DataverseName, IAType>> getFunctionTypeArgs(ARecord functionRecord) throws AlgebricksException {
- String dv = "";
- String type = "";
- boolean unknownable = false;
- List<Pair<DataverseName, IAType>> functionArgs = new ArrayList<>();
-
- final ARecordType functionType = functionRecord.getType();
- final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_ARGTYPES_FIELD_NAME);
- if (functionLibraryIdx >= 0) {
- IACursor cursor = ((AOrderedList) functionRecord.getValueByPos(functionLibraryIdx)).getCursor();
- while (cursor.next()) {
- ARecord field = (ARecord) cursor.get();
- final ARecordType fieldType = field.getType();
- final int keyIdx = fieldType.getFieldIndex(TYPE_DV_FIELD_NAME);
- if (keyIdx >= 0) {
- dv = ((AString) field.getValueByPos(keyIdx)).getStringValue();
- }
- final int valueIdx = fieldType.getFieldIndex(TYPE_NAME_FIELD_NAME);
- if (valueIdx >= 0) {
- type = ((AString) field.getValueByPos(valueIdx)).getStringValue();
- }
- final int unknownableIdx = fieldType.getFieldIndex(TYPE_UNKNOWNABLE_FIELD_NAME);
- if (unknownableIdx >= 0) {
- unknownable = Boolean.valueOf(((AString) field.getValueByPos(valueIdx)).getStringValue());
- }
- functionArgs.add(resolveTypePair(dv, type, unknownable));
- }
- }
- return functionArgs;
- }
-
- private Pair<DataverseName, IAType> getFunctionReturnType(ARecord functionRecord) throws AlgebricksException {
- String returnType = ((AString) functionRecord
- .getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX)).getStringValue();
- DataverseName complete = DataverseName.createFromCanonicalForm(returnType);
- DataverseName dvName = DataverseName.create(complete.getParts(), 0, complete.getParts().size() - 1);
- String typeName = complete.getParts().get(complete.getParts().size() - 1);
- return resolveTypePair(dvName.getCanonicalForm(), typeName, getUnknownable(functionRecord));
- }
-
protected Function createMetadataEntityFromARecord(ARecord functionRecord) throws AlgebricksException {
String dataverseCanonicalName =
((AString) functionRecord.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_DATAVERSENAME_FIELD_INDEX))
@@ -219,8 +105,8 @@
String functionName =
((AString) functionRecord.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTIONNAME_FIELD_INDEX))
.getStringValue();
- String arity = ((AString) functionRecord
- .getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_ARITY_FIELD_INDEX)).getStringValue();
+ int arity = Integer.parseInt(((AString) functionRecord
+ .getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_ARITY_FIELD_INDEX)).getStringValue());
IACursor argCursor = ((AOrderedList) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX)).getCursor();
@@ -229,15 +115,29 @@
argNames.add(((AString) argCursor.get()).getStringValue());
}
+ List<IAType> argTypes = getArgTypes(functionRecord, dataverseName, arity);
+
+ 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 definition = ((AString) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEFINITION_FIELD_INDEX)).getStringValue();
-
- String language = ((AString) functionRecord
+ String languageValue = ((AString) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_LANGUAGE_FIELD_INDEX)).getStringValue();
-
+ Function.FunctionLanguage language = Function.FunctionLanguage.findByName(languageValue);
+ if (language == null) {
+ throw new IllegalStateException(languageValue);
+ }
String functionKind =
((AString) functionRecord.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_KIND_FIELD_INDEX))
.getStringValue();
+ String functionLibrary = getString(functionRecord, FUNCTION_ARECORD_FUNCTION_LIBRARY_FIELD_NAME);
+ 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);
IACursor dependenciesCursor = ((AOrderedList) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEPENDENCIES_FIELD_INDEX)).getCursor();
@@ -253,17 +153,41 @@
dependencies.add(dependencyList);
}
- List<Pair<DataverseName, IAType>> args = getFunctionTypeArgs(functionRecord);
- Pair<DataverseName, IAType> returnType = getFunctionReturnType(functionRecord);
- String functionLibrary = getFunctionLibrary(functionRecord);
- Map<String, String> params = getFunctionWithParams(functionRecord);
- boolean unknownable = getUnknownable(functionRecord);
- boolean nullCall = getNullCall(functionRecord);
- boolean deterministic = getDeterministic(functionRecord);
+ FunctionSignature signature = new FunctionSignature(dataverseName, functionName, arity);
- FunctionSignature signature = new FunctionSignature(dataverseName, functionName, Integer.parseInt(arity));
- return new Function(signature, args, argNames, returnType, definition, language, unknownable, nullCall,
- deterministic, functionLibrary, functionKind, dependencies, params);
+ return new Function(signature, argNames, argTypes, returnType, definition, functionKind, language,
+ functionLibrary, nullCall, deterministic, params, dependencies);
+ }
+
+ private IAType resolveType(DataverseName dataverseName, String typeName, Boolean isUnknownable)
+ throws AlgebricksException {
+ return BuiltinType.ANY.getTypeName().equalsIgnoreCase(typeName) ? BuiltinType.ANY
+ : BuiltinTypeMap.getTypeFromTypeName(metadataNode, txnId, dataverseName, typeName,
+ isUnknownable != null ? isUnknownable : false);
+ }
+
+ private List<IAType> getArgTypes(ARecord functionRecord, DataverseName dataverseName, int arity)
+ throws AlgebricksException {
+ List<IAType> argTypes = new ArrayList<>(arity);
+
+ ARecordType functionRecordType = functionRecord.getType();
+ int paramTypesFieldIdx = functionRecordType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_PARAMTYPES_FIELD_NAME);
+ if (paramTypesFieldIdx >= 0) {
+ IACursor cursor = ((AOrderedList) functionRecord.getValueByPos(paramTypesFieldIdx)).getCursor();
+ 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);
+ }
+ } else {
+ for (int i = 0; i < arity; i++) {
+ argTypes.add(BuiltinType.ANY);
+ }
+ }
+ return argTypes;
}
private Triple<DataverseName, String, String> getDependency(AOrderedList dependencySubnames) {
@@ -280,9 +204,41 @@
return new Triple<>(dataverseName, second, third);
}
+ private Map<String, String> getWithParameters(ARecord functionRecord) {
+ Map<String, String> adaptorConfiguration = new HashMap<>();
+ final ARecordType functionType = functionRecord.getType();
+ final int functionLibraryIdx = functionType.getFieldIndex(FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME);
+ if (functionLibraryIdx >= 0) {
+ IACursor cursor = ((AOrderedList) functionRecord.getValueByPos(functionLibraryIdx)).getCursor();
+ while (cursor.next()) {
+ ARecord field = (ARecord) cursor.get();
+ final ARecordType fieldType = field.getType();
+ final int keyIdx = fieldType.getFieldIndex(PROPERTIES_NAME_FIELD_NAME);
+ String key = keyIdx >= 0 ? ((AString) field.getValueByPos(keyIdx)).getStringValue() : "";
+ final int valueIdx = fieldType.getFieldIndex(PROPERTIES_VALUE_FIELD_NAME);
+ String value = valueIdx >= 0 ? ((AString) field.getValueByPos(valueIdx)).getStringValue() : "";
+ adaptorConfiguration.put(key, value);
+ }
+ }
+ return adaptorConfiguration;
+ }
+
+ private String getString(ARecord aRecord, String fieldName) {
+ final ARecordType functionType = aRecord.getType();
+ final int functionLibraryIdx = functionType.getFieldIndex(fieldName);
+ return functionLibraryIdx >= 0 ? ((AString) aRecord.getValueByPos(functionLibraryIdx)).getStringValue() : null;
+ }
+
+ private Boolean getBoolean(ARecord aRecord, String fieldName) {
+ final ARecordType functionType = aRecord.getType();
+ final int fieldIndex = functionType.getFieldIndex(fieldName);
+ return fieldIndex >= 0 ? ((ABoolean) aRecord.getValueByPos(fieldIndex)).getBoolean() : null;
+ }
+
@Override
public ITupleReference getTupleFromMetadataEntity(Function function) throws HyracksDataException {
- String dataverseCanonicalName = function.getDataverseName().getCanonicalForm();
+ DataverseName dataverseName = function.getDataverseName();
+ String dataverseCanonicalName = dataverseName.getCanonicalForm();
// write the key in the first 2 fields of the tuple
tupleBuilder.reset();
@@ -325,7 +281,7 @@
.getFieldTypes()[MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_PARAM_LIST_FIELD_INDEX]);
for (String p : function.getArgNames()) {
itemValue.reset();
- aString.setValue(p == null ? BuiltinType.ANY.toString() : p);
+ aString.setValue(p);
stringSerde.serialize(aString, itemValue.getDataOutput());
listBuilder.addItem(itemValue);
}
@@ -333,10 +289,17 @@
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
fieldValue.reset();
- aString.setValue(
- function.getReturnType().getFirst().getCanonicalForm() + '.' + function.getReturnType().getSecond());
+ aString.setValue(returnPrimeType.getTypeName());
stringSerde.serialize(aString, fieldValue.getDataOutput());
recordBuilder.addField(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX, fieldValue);
@@ -348,7 +311,7 @@
// write field 6
fieldValue.reset();
- aString.setValue(function.getLanguage());
+ aString.setValue(function.getLanguage().getName());
stringSerde.serialize(aString, fieldValue.getDataOutput());
recordBuilder.addField(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_LANGUAGE_FIELD_INDEX, fieldValue);
@@ -385,7 +348,7 @@
dependenciesListBuilder.write(fieldValue.getDataOutput(), true);
recordBuilder.addField(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEPENDENCIES_FIELD_INDEX, fieldValue);
- writeOpenFields(function);
+ writeOpenFields(function, returnPrimeType, returnTypeIsUnknownable);
// write record
recordBuilder.write(tupleBuilder.getDataOutput(), true);
@@ -395,63 +358,67 @@
return tuple;
}
- protected void writeOpenFields(Function function) throws HyracksDataException {
+ protected void writeOpenFields(Function function, IAType returnPrimeType, boolean returnTypeIsUnknownable)
+ throws HyracksDataException {
+ writeReturnTypeIsNullable(returnPrimeType, returnTypeIsUnknownable);
writeArgTypes(function);
writeWithParameters(function);
writeLibrary(function);
- writeUnknownable(function);
writeNullCall(function);
writeDeterministic(function);
}
protected void writeWithParameters(Function function) throws HyracksDataException {
+ Map<String, String> withParams = function.getParams();
+ if (withParams == null || withParams.isEmpty()) {
+ return;
+ }
+
OrderedListBuilder listBuilder = new OrderedListBuilder();
ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
- fieldName.reset();
- aString.setValue(FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME);
- stringSerde.serialize(aString, fieldName.getDataOutput());
listBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
- for (Map.Entry<String, String> property : function.getParams().entrySet()) {
- String name = property.getKey();
- String value = property.getValue();
+ for (Map.Entry<String, String> property : withParams.entrySet()) {
itemValue.reset();
- writePropertyTypeRecord(name, value, itemValue.getDataOutput());
+ writePropertyTypeRecord(property.getKey(), property.getValue(), itemValue.getDataOutput());
listBuilder.addItem(itemValue);
}
fieldValue.reset();
listBuilder.write(fieldValue.getDataOutput(), true);
+
+ fieldName.reset();
+ aString.setValue(FUNCTION_ARECORD_FUNCTION_WITHPARAM_LIST_NAME);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+
recordBuilder.addField(fieldName, fieldValue);
}
protected void writeArgTypes(Function function) throws HyracksDataException {
+ DataverseName dataverseName = function.getDataverseName();
OrderedListBuilder listBuilder = new OrderedListBuilder();
ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
- fieldName.reset();
- aString.setValue(FUNCTION_ARECORD_FUNCTION_ARGTYPES_FIELD_NAME);
- stringSerde.serialize(aString, fieldName.getDataOutput());
listBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
- for (Pair<DataverseName, IAType> p : function.getArguments()) {
- String dv = p.getFirst().getCanonicalForm();
- String type = p.getSecond().getTypeName();
+ 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);
+ }
itemValue.reset();
- writeTypeRecord(dv, type, isNullableType(p.getSecond()), itemValue.getDataOutput());
+ writeTypeRecord(argPrimeType, argTypeIsUnknownable, itemValue.getDataOutput());
listBuilder.addItem(itemValue);
}
fieldValue.reset();
listBuilder.write(fieldValue.getDataOutput(), true);
+
+ fieldName.reset();
+ aString.setValue(FUNCTION_ARECORD_FUNCTION_PARAMTYPES_FIELD_NAME);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+
recordBuilder.addField(fieldName, fieldValue);
}
- protected boolean isNullableType(IAType definedType) {
- if ((definedType.getTypeTag() != ATypeTag.UNION) || (definedType.getTypeTag() == ATypeTag.ANY)) {
- return false;
- }
-
- return ((AUnionType) definedType).isNullableType();
- }
-
protected void writeLibrary(Function function) throws HyracksDataException {
- if (null == function.getLibrary()) {
+ if (function.getLibrary() == null) {
return;
}
fieldName.reset();
@@ -463,48 +430,49 @@
recordBuilder.addField(fieldName, fieldValue);
}
- protected void writeUnknownable(Function function) throws HyracksDataException {
- fieldName.reset();
- aString.setValue(FUNCTION_ARECORD_FUNCTION_NULLABILITY_FIELD_NAME);
- stringSerde.serialize(aString, fieldName.getDataOutput());
- fieldValue.reset();
- aString.setValue(Boolean.toString(function.isUnknownable()));
- stringSerde.serialize(aString, fieldValue.getDataOutput());
- recordBuilder.addField(fieldName, fieldValue);
+ protected void writeReturnTypeIsNullable(IAType returnPrimeType, boolean returnTypeIsUnknownable)
+ throws HyracksDataException {
+ if (returnPrimeType.getTypeTag() != ATypeTag.ANY) {
+ fieldName.reset();
+ aString.setValue(FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_IS_NULLABLE);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+ fieldValue.reset();
+ booleanSerde.serialize(ABoolean.valueOf(returnTypeIsUnknownable), fieldValue.getDataOutput());
+ recordBuilder.addField(fieldName, fieldValue);
+ }
}
protected void writeNullCall(Function function) throws HyracksDataException {
+ if (function.getNullCall() == null) {
+ return;
+ }
fieldName.reset();
aString.setValue(FUNCTION_ARECORD_FUNCTION_NULLCALL_FIELD_NAME);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
- aString.setValue(Boolean.toString(function.isNullCall()));
- stringSerde.serialize(aString, fieldValue.getDataOutput());
+ booleanSerde.serialize(ABoolean.valueOf(function.getNullCall()), fieldValue.getDataOutput());
recordBuilder.addField(fieldName, fieldValue);
}
protected void writeDeterministic(Function function) throws HyracksDataException {
+ if (function.getDeterministic() == null) {
+ return;
+ }
fieldName.reset();
aString.setValue(FUNCTION_ARECORD_FUNCTION_DETERMINISTIC_FIELD_NAME);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
- aString.setValue(Boolean.toString(function.isDeterministic()));
- stringSerde.serialize(aString, fieldValue.getDataOutput());
+ booleanSerde.serialize(ABoolean.valueOf(function.getDeterministic()), fieldValue.getDataOutput());
recordBuilder.addField(fieldName, fieldValue);
}
public void writePropertyTypeRecord(String name, String value, DataOutput out) throws HyracksDataException {
IARecordBuilder propertyRecordBuilder = new RecordBuilder();
- ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
- ArrayBackedValueStorage fieldName = new ArrayBackedValueStorage();
propertyRecordBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
- AMutableString aString = new AMutableString("");
- ISerializerDeserializer<AString> stringSerde =
- SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING);
// write field 0
fieldName.reset();
- aString.setValue("name");
+ aString.setValue(FIELD_NAME_NAME);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
aString.setValue(name);
@@ -514,7 +482,7 @@
// write field 1
fieldName.reset();
- aString.setValue("value");
+ aString.setValue(FIELD_NAME_VALUE);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
aString.setValue(value);
@@ -525,45 +493,28 @@
propertyRecordBuilder.write(out, true);
}
- public void writeTypeRecord(String dataverse, String type, boolean unknownable, DataOutput out)
- throws HyracksDataException {
+ public void writeTypeRecord(IAType primeType, boolean isUnknownable, DataOutput out) throws HyracksDataException {
IARecordBuilder propertyRecordBuilder = new RecordBuilder();
- ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
- ArrayBackedValueStorage fieldName = new ArrayBackedValueStorage();
propertyRecordBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
- AMutableString aString = new AMutableString("");
- ISerializerDeserializer<AString> stringSerde =
- SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING);
- // write field 0
+ // write field "Type"
fieldName.reset();
- aString.setValue(TYPE_DV_FIELD_NAME);
+ aString.setValue(FIELD_NAME_TYPE);
stringSerde.serialize(aString, fieldName.getDataOutput());
fieldValue.reset();
- aString.setValue(dataverse);
+ aString.setValue(primeType.getTypeName());
stringSerde.serialize(aString, fieldValue.getDataOutput());
-
propertyRecordBuilder.addField(fieldName, fieldValue);
- // write field 1
- fieldName.reset();
- aString.setValue(TYPE_NAME_FIELD_NAME);
- stringSerde.serialize(aString, fieldName.getDataOutput());
- fieldValue.reset();
- aString.setValue(type);
- stringSerde.serialize(aString, fieldValue.getDataOutput());
-
- propertyRecordBuilder.addField(fieldName, fieldValue);
-
- // write field 2
- fieldName.reset();
- aString.setValue(TYPE_UNKNOWNABLE_FIELD_NAME);
- stringSerde.serialize(aString, fieldName.getDataOutput());
- fieldValue.reset();
- aString.setValue(Boolean.toString(unknownable));
- stringSerde.serialize(aString, fieldValue.getDataOutput());
-
- propertyRecordBuilder.addField(fieldName, fieldValue);
+ // write field "IsNullable"
+ if (primeType.getTypeTag() != ATypeTag.ANY) {
+ fieldName.reset();
+ aString.setValue(FIELD_NAME_IS_NULLABLE);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+ fieldValue.reset();
+ booleanSerde.serialize(ABoolean.valueOf(isUnknownable), fieldValue.getDataOutput());
+ propertyRecordBuilder.addField(fieldName, fieldValue);
+ }
propertyRecordBuilder.write(out, true);
}
@@ -579,4 +530,4 @@
}
return dependencySubnames;
}
-}
+}
\ No newline at end of file
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 db3e1c0..2469ff2 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,15 +18,11 @@
*/
package org.apache.asterix.metadata.functions;
-import java.util.List;
-import java.util.stream.Collectors;
-
import org.apache.asterix.metadata.MetadataTransactionContext;
import org.apache.asterix.metadata.entities.Function;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.asterix.om.types.IAType;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
@@ -55,13 +51,12 @@
private static IFunctionInfo getScalarFunctionInfo(MetadataTransactionContext txnCtx, Function function)
throws AlgebricksException {
- List<IAType> argumentTypes = function.getArguments().stream().map(Pair::getSecond).collect(Collectors.toList());
- IAType returnType = function.getReturnType().getSecond();
- IResultTypeComputer typeComputer = new ExternalTypeComputer(returnType, argumentTypes);
+ IAType returnType = function.getReturnType();
+ IResultTypeComputer typeComputer = new ExternalTypeComputer(returnType, function.getArgTypes());
return new ExternalScalarFunctionInfo(function.getSignature().createFunctionIdentifier(), returnType,
- function.getFunctionBody(), function.getLanguage(), function.getLibrary(), argumentTypes,
- function.getParams(), typeComputer);
+ function.getFunctionBody(), function.getLanguage().getName(), function.getLibrary(),
+ function.getArgTypes(), function.getParams(), typeComputer);
}
private static IFunctionInfo getUnnestFunctionInfo(MetadataTransactionContext txnCtx, Function function) {
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
index 66a05bf..edaabc9 100644
--- 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
@@ -24,13 +24,10 @@
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.bootstrap.MetadataBuiltinEntities;
import org.apache.asterix.metadata.entities.Function;
-import org.apache.asterix.om.types.AUnorderedListType;
import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.utils.Pair;
import org.junit.Assert;
import org.junit.Test;
@@ -40,17 +37,15 @@
// 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<>(),
- new Pair<>(MetadataBuiltinEntities.DEFAULT_DATAVERSE_NAME,
- new AUnorderedListType(BuiltinType.ASTRING, "foo")),
- "", "JAVA", false, false, false, "", "SCALAR", null, null);
+ Function function = new Function(signature, new LinkedList<>(), new LinkedList<>(), BuiltinType.ASTRING, "",
+ "SCALAR", Function.FunctionLanguage.JAVA, "", false, false, null, null);
// when
ExternalScalarFunctionInfo info =
(ExternalScalarFunctionInfo) ExternalFunctionCompilerUtil.getExternalFunctionInfo(txnCtx, function);
// then
- IAType expectedType = new AUnorderedListType(BuiltinType.ASTRING, "AUnorderedList");
+ IAType expectedType = BuiltinType.ASTRING;
Assert.assertEquals(expectedType, info.getReturnType());
}
}
diff --git a/asterixdb/asterix-tools/src/test/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java b/asterixdb/asterix-tools/src/test/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java
index 1bb7728..07a7234 100644
--- a/asterixdb/asterix-tools/src/test/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java
+++ b/asterixdb/asterix-tools/src/test/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java
@@ -56,9 +56,8 @@
TypeDecl td = (TypeDecl) stmt;
DataverseName typeDataverse = td.getDataverseName() == null ? defaultDataverse : td.getDataverseName();
- Map<TypeSignature, IAType> typeInStmt = TypeTranslator.computeTypes(mdTxnCtx, td.getTypeDef(),
- td.getIdent().getValue(), typeDataverse, types);
- types.putAll(typeInStmt);
+ TypeTranslator.computeTypes(typeDataverse, td.getIdent().getValue(), td.getTypeDef(), defaultDataverse,
+ mdTxnCtx, types);
TypeSignature signature = new TypeSignature(typeDataverse, td.getIdent().getValue());
TypeDataGen tdg = td.getDatagenAnnotation();