[NO ISSUE][COMP] CREATE OR REPLACE FUNCTION
- user model changes: yes
- storage format changes: no
- interface changes: no
Details:
- Support CREATE OR REPLACE FUNCTION
- Support parameter list in DROP FUNCTION
- Replace "any" type in function metadata with null
- Refactor builtin function registry
- Align inline type handling in
CREATE/DROP FUNCTION/DATASET
Change-Id: Ie603fa9c228a4d1b0fc0ed8275a9b2188e7007d9
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/7543
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: 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/optimizer/base/AsterixOptimizationContext.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
index 20673eb..51c03eb 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
@@ -23,7 +23,6 @@
import java.util.Set;
import org.apache.asterix.metadata.declared.DataSource;
-import org.apache.asterix.metadata.declared.DataSourceId;
import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint;
import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
@@ -40,7 +39,7 @@
public final class AsterixOptimizationContext extends AlgebricksOptimizationContext {
- private final Int2ObjectMap<Set<DataSourceId>> dataSourceMap = new Int2ObjectOpenHashMap<>();
+ private final Int2ObjectMap<Set<DataSource>> dataSourceMap = new Int2ObjectOpenHashMap<>();
public AsterixOptimizationContext(int varCounter, IExpressionEvalSizeComputer expressionEvalSizeComputer,
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
@@ -55,15 +54,15 @@
public void addDataSource(DataSource dataSource) {
byte type = dataSource.getDatasourceType();
- Set<DataSourceId> set = dataSourceMap.get(type);
+ Set<DataSource> set = dataSourceMap.get(type);
if (set == null) {
set = new HashSet<>();
dataSourceMap.put(type, set);
}
- set.add(dataSource.getId());
+ set.add(dataSource);
}
- public Int2ObjectMap<Set<DataSourceId>> getDataSourceMap() {
+ public Int2ObjectMap<Set<DataSource>> getDataSourceMap() {
return dataSourceMap;
}
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java
index 916fd75..43136c0 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java
@@ -142,7 +142,7 @@
ILogicalExpression cExp = new ConstantExpression(new AsterixConstantValue(list));
Mutable<ILogicalExpression> mutCExp = new MutableObject<>(cExp);
- IFunctionInfo scanFctInfo = BuiltinFunctions.getAsterixFunctionInfo(BuiltinFunctions.SCAN_COLLECTION);
+ IFunctionInfo scanFctInfo = BuiltinFunctions.getBuiltinFunctionInfo(BuiltinFunctions.SCAN_COLLECTION);
UnnestingFunctionCallExpression scanExp = new UnnestingFunctionCallExpression(scanFctInfo, mutCExp);
scanExp.setSourceLocation(sourceLoc);
LogicalVariable scanVar = context.newVar();
@@ -151,7 +151,7 @@
unn.getInputs().add(new MutableObject<>(ets));
context.computeAndSetTypeEnvironmentForOperator(unn);
- IFunctionInfo eqFctInfo = BuiltinFunctions.getAsterixFunctionInfo(AlgebricksBuiltinFunctions.EQ);
+ IFunctionInfo eqFctInfo = BuiltinFunctions.getBuiltinFunctionInfo(AlgebricksBuiltinFunctions.EQ);
AbstractFunctionCallExpression eqExp = new ScalarFunctionCallExpression(eqFctInfo);
eqExp.setSourceLocation(sourceLoc);
VariableReferenceExpression scanVarRef = new VariableReferenceExpression(scanVar);
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
index cc91c06..34a256b 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
@@ -21,15 +21,26 @@
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.function.BiFunction;
import org.apache.asterix.aqlplus.parser.AQLPlusParser;
import org.apache.asterix.aqlplus.parser.ParseException;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.lang.aql.clause.JoinClause;
+import org.apache.asterix.lang.aql.clause.MetaVariableClause;
+import org.apache.asterix.lang.aql.expression.MetaVariableExpr;
+import org.apache.asterix.lang.aql.rewrites.visitor.AqlFunctionCallResolverVisitor;
+import org.apache.asterix.lang.aql.visitor.base.IAQLPlusVisitor;
import org.apache.asterix.lang.common.base.Clause;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.metadata.declared.MetadataProvider;
@@ -427,6 +438,12 @@
throw CompilationException.create(ErrorCode.COMPILATION_TRANSLATION_ERROR, e);
}
+ AqlPlusFunctionCallResolverVisitor fnResolverVisitor =
+ new AqlPlusFunctionCallResolverVisitor(metadataProvider, Collections.emptyList());
+ for (Clause clause : clauses) {
+ clause.accept(fnResolverVisitor, null);
+ }
+
// Step 4. The essential substitution with translator.
ILogicalPlan plan;
try {
@@ -501,4 +518,40 @@
}
return new ArrayList<>(primaryKeys);
}
+
+ private static final class AqlPlusFunctionCallResolverVisitor extends AqlFunctionCallResolverVisitor
+ implements IAQLPlusVisitor<Expression, ILangExpression> {
+ private AqlPlusFunctionCallResolverVisitor(MetadataProvider metadataProvider,
+ List<FunctionDecl> declaredFunctions) {
+ super(metadataProvider, declaredFunctions);
+ }
+
+ @Override
+ protected BiFunction<String, Integer, FunctionSignature> createBuiltinFunctionResolver(
+ MetadataProvider metadataProvider) {
+ return FunctionUtil.createBuiltinFunctionResolver(true);
+ }
+
+ @Override
+ public Expression visitJoinClause(JoinClause joinClause, ILangExpression arg) throws CompilationException {
+ for (Clause clause : joinClause.getLeftClauses()) {
+ clause.accept(this, arg);
+ }
+ for (Clause clause : joinClause.getRightClauses()) {
+ clause.accept(this, arg);
+ }
+ joinClause.getWhereExpr().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Expression visitMetaVariableClause(MetaVariableClause c, ILangExpression arg) {
+ return null;
+ }
+
+ @Override
+ public Expression visitMetaVariableExpr(MetaVariableExpr v, ILangExpression arg) {
+ return v;
+ }
+ }
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
index 8f5bd9c..d3eb0c2 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
@@ -19,7 +19,6 @@
package org.apache.asterix.optimizer.rules;
-import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.asterix.om.functions.ExternalFunctionInfo;
import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
@@ -69,7 +68,7 @@
}
}
// if the current function is builtin function, skip the type casting
- if (BuiltinFunctions.getBuiltinFunctionIdentifier(funcCallExpr.getFunctionIdentifier()) != null) {
+ if (BuiltinFunctions.getBuiltinFunctionInfo(funcCallExpr.getFunctionIdentifier()) != null) {
return changed;
}
IAType inputType;
@@ -97,8 +96,8 @@
checkUnknown = true;
}
if (castFlag || checkUnknown) {
- AbstractFunctionCallExpression castFunc =
- new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE));
+ AbstractFunctionCallExpression castFunc = new ScalarFunctionCallExpression(
+ BuiltinFunctions.getBuiltinFunctionInfo(BuiltinFunctions.CAST_TYPE));
castFunc.setSourceLocation(argExpr.getValue().getSourceLocation());
castFunc.getArguments().add(argExpr);
TypeCastUtils.setRequiredAndInputTypes(castFunc, reqArgType, inputType);
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RewriteDistinctAggregateRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RewriteDistinctAggregateRule.java
index 92b1ab6..9d0ee59 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RewriteDistinctAggregateRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RewriteDistinctAggregateRule.java
@@ -321,7 +321,7 @@
if (regularAggForDistinct == null) {
throw new IllegalStateException(String.valueOf(callExpr.getFunctionIdentifier()));
}
- callExpr.setFunctionInfo(BuiltinFunctions.getAsterixFunctionInfo(regularAggForDistinct));
+ callExpr.setFunctionInfo(BuiltinFunctions.getBuiltinFunctionInfo(regularAggForDistinct));
if (assignOp != null) {
callExpr.getArguments().get(0).setValue(distinctVarRef.cloneExpression());
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetAsterixMemoryRequirementsRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetAsterixMemoryRequirementsRule.java
index f4f8fa2..abe4b71 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetAsterixMemoryRequirementsRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetAsterixMemoryRequirementsRule.java
@@ -22,9 +22,8 @@
import java.util.Set;
import java.util.function.Predicate;
-import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.metadata.declared.DataSource;
-import org.apache.asterix.metadata.declared.DataSourceId;
+import org.apache.asterix.metadata.declared.FunctionDataSource;
import org.apache.asterix.metadata.utils.MetadataConstants;
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.asterix.optimizer.base.AsterixOptimizationContext;
@@ -53,13 +52,13 @@
}
private boolean forceMinMemoryBudget(AsterixOptimizationContext context) {
- Int2ObjectMap<Set<DataSourceId>> dataSourceMap = context.getDataSourceMap();
+ Int2ObjectMap<Set<DataSource>> dataSourceMap = context.getDataSourceMap();
if (dataSourceMap.isEmpty()) {
return false;
}
- for (Int2ObjectMap.Entry<Set<DataSourceId>> me : dataSourceMap.int2ObjectEntrySet()) {
+ for (Int2ObjectMap.Entry<Set<DataSource>> me : dataSourceMap.int2ObjectEntrySet()) {
int dataSourceType = me.getIntKey();
- Predicate<DataSourceId> dataSourceTest;
+ Predicate<DataSource> dataSourceTest;
switch (dataSourceType) {
case DataSource.Type.INTERNAL_DATASET:
dataSourceTest = SetAsterixMemoryRequirementsRule::isMinMemoryBudgetDataset;
@@ -77,13 +76,13 @@
return true;
}
- private static boolean isMinMemoryBudgetDataset(DataSourceId dsId) {
- return MetadataConstants.METADATA_DATAVERSE_NAME.equals(dsId.getDataverseName());
+ private static boolean isMinMemoryBudgetDataset(DataSource ds) {
+ return MetadataConstants.METADATA_DATAVERSE_NAME.equals(ds.getId().getDataverseName());
}
- private static boolean isMinMemoryBudgetFunction(DataSourceId dsId) {
- return BuiltinFunctions.builtinFunctionHasProperty(
- FunctionSignature.createFunctionIdentifier(dsId.getDataverseName(), dsId.getDatasourceName()),
+ private static boolean isMinMemoryBudgetFunction(DataSource ds) {
+ FunctionDataSource fds = (FunctionDataSource) ds;
+ return BuiltinFunctions.builtinFunctionHasProperty(fds.getFunctionId(),
BuiltinFunctions.DataSourceFunctionProperty.MIN_MEMORY_BUDGET);
}
}
\ No newline at end of file
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/UnnestToDataScanRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/UnnestToDataScanRule.java
index 0d02385..eabe977 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/UnnestToDataScanRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/UnnestToDataScanRule.java
@@ -19,6 +19,7 @@
package org.apache.asterix.optimizer.rules;
import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionToDataSourceRewriter;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -46,7 +47,12 @@
if (f == null) {
return false;
}
- return BuiltinFunctions.getDatasourceTransformer(f.getFunctionIdentifier()).rewrite(opRef, context);
+ IFunctionToDataSourceRewriter transformer =
+ BuiltinFunctions.getDatasourceTransformer(f.getFunctionIdentifier());
+ if (transformer == null) {
+ return false;
+ }
+ return transformer.rewrite(opRef, context);
}
public static AbstractFunctionCallExpression getFunctionCall(Mutable<ILogicalOperator> opRef) {
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 4bb1adf..17bc77c 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
@@ -36,7 +36,6 @@
import org.apache.asterix.common.dataflow.ICcApplicationContext;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
-import org.apache.asterix.common.functions.FunctionConstants;
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
@@ -90,8 +89,8 @@
import org.apache.asterix.om.base.AString;
import org.apache.asterix.om.base.IAObject;
import org.apache.asterix.om.constants.AsterixConstantValue;
+import org.apache.asterix.om.functions.BuiltinFunctionInfo;
import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.asterix.om.functions.FunctionInfo;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
@@ -883,7 +882,7 @@
List<Mutable<ILogicalExpression>> args, SourceLocation sourceLoc) throws CompilationException {
AbstractFunctionCallExpression f;
if ((f = lookupUserDefinedFunction(signature, args, sourceLoc)) == null) {
- f = lookupBuiltinFunction(signature.getName(), signature.getArity(), args, sourceLoc);
+ f = lookupBuiltinFunction(signature, args, sourceLoc);
}
return f;
}
@@ -895,24 +894,25 @@
if (function == null) {
return null;
}
- IFunctionInfo finfo = function.isExternal()
- ? ExternalFunctionCompilerUtil.getExternalFunctionInfo(metadataProvider, function)
- : FunctionUtil.getFunctionInfo(signature);
+ if (!function.isExternal()) {
+ // all non-external UDFs should've been inlined by now
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, signature);
+ }
+ IFunctionInfo finfo = ExternalFunctionCompilerUtil.getExternalFunctionInfo(metadataProvider, function);
AbstractFunctionCallExpression f = new ScalarFunctionCallExpression(finfo, args);
f.setSourceLocation(sourceLoc);
return f;
+ } catch (CompilationException e) {
+ throw e;
} catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, e.getMessage(), e);
+ throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, sourceLoc, e.getMessage());
}
}
- private AbstractFunctionCallExpression lookupBuiltinFunction(String functionName, int arity,
- List<Mutable<ILogicalExpression>> args, SourceLocation sourceLoc) {
+ private AbstractFunctionCallExpression lookupBuiltinFunction(FunctionSignature signature,
+ List<Mutable<ILogicalExpression>> args, SourceLocation sourceLoc) throws CompilationException {
AbstractFunctionCallExpression f;
- FunctionIdentifier fi = getBuiltinFunctionIdentifier(functionName, arity);
- if (fi == null) {
- return null;
- }
+ FunctionIdentifier fi = signature.createFunctionIdentifier();
if (BuiltinFunctions.isBuiltinAggregateFunction(fi)) {
f = BuiltinFunctions.makeAggregateFunctionExpression(fi, args);
} else if (BuiltinFunctions.isBuiltinUnnestingFunction(fi)) {
@@ -923,29 +923,17 @@
} else if (BuiltinFunctions.isWindowFunction(fi)) {
f = BuiltinFunctions.makeWindowFunctionExpression(fi, args);
} else {
- f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fi), args);
+ BuiltinFunctionInfo finfo = FunctionUtil.getFunctionInfo(fi);
+ if (finfo == null) {
+ // should've been resolved earlier
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, fi);
+ }
+ f = new ScalarFunctionCallExpression(finfo, args);
}
f.setSourceLocation(sourceLoc);
return f;
}
- protected FunctionIdentifier getBuiltinFunctionIdentifier(String functionName, int arity) {
- FunctionIdentifier fi = new FunctionIdentifier(AlgebricksBuiltinFunctions.ALGEBRICKS_NS, functionName, arity);
- FunctionInfo afi = BuiltinFunctions.lookupFunction(fi);
- FunctionIdentifier builtinAquafi = afi == null ? null : afi.getFunctionIdentifier();
-
- if (builtinAquafi != null) {
- fi = builtinAquafi;
- } else {
- fi = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, functionName, arity);
- afi = BuiltinFunctions.lookupFunction(fi);
- if (afi == null) {
- return null;
- }
- }
- return fi;
- }
-
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(FunctionDecl fd, Mutable<ILogicalOperator> tupSource) {
throw new IllegalStateException("Function declarations should be inlined at AST rewriting phase.");
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index c3fc56c..c394722 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -113,6 +113,7 @@
import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestNonMapOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestOperator;
@@ -1071,11 +1072,12 @@
List<Expression> fargs = winExpr.getExprList();
FunctionSignature fs = winExpr.getFunctionSignature();
- FunctionIdentifier fi = getBuiltinFunctionIdentifier(fs.getName(), fs.getArity());
- if (fi == null) {
+ IFunctionInfo finfo = BuiltinFunctions.getBuiltinFunctionInfo(fs.createFunctionIdentifier());
+ if (finfo == null) {
throw new CompilationException(ErrorCode.COMPILATION_EXPECTED_WINDOW_FUNCTION, winExpr.getSourceLocation(),
fs.getName());
}
+ FunctionIdentifier fi = finfo.getFunctionIdentifier();
boolean isWin = BuiltinFunctions.isWindowFunction(fi);
boolean isWinAgg = isWin && BuiltinFunctions.builtinFunctionHasProperty(fi,
BuiltinFunctions.WindowFunctionProperty.HAS_LIST_ARG);
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/ActiveRequestsDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/ActiveRequestsDatasource.java
index 2afd11c..24a127a 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/ActiveRequestsDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/ActiveRequestsDatasource.java
@@ -33,7 +33,7 @@
createDataSourceId(ActiveRequestsRewriter.ACTIVE_REQUESTS);
public ActiveRequestsDatasource(INodeDomain domain) throws AlgebricksException {
- super(ACTIVE_REQUESTS_DATASOURCE_ID, domain);
+ super(ACTIVE_REQUESTS_DATASOURCE_ID, ActiveRequestsRewriter.ACTIVE_REQUESTS, domain);
}
@Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/CompletedRequestsDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/CompletedRequestsDatasource.java
index 1fe103e..0bfbff1 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/CompletedRequestsDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/CompletedRequestsDatasource.java
@@ -33,7 +33,7 @@
createDataSourceId(CompletedRequestsRewriter.COMPLETED_REQUESTS);
public CompletedRequestsDatasource(INodeDomain domain) throws AlgebricksException {
- super(COMPLETED_REQUESTS_DATASOURCE_ID, domain);
+ super(COMPLETED_REQUESTS_DATASOURCE_ID, CompletedRequestsRewriter.COMPLETED_REQUESTS, domain);
}
@Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetResourcesDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetResourcesDatasource.java
index ffd04ab..3e5033b 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetResourcesDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetResourcesDatasource.java
@@ -34,7 +34,7 @@
private final int datasetId;
public DatasetResourcesDatasource(INodeDomain domain, int datasetId) throws AlgebricksException {
- super(DATASET_RESOURCES_DATASOURCE_ID, domain);
+ super(DATASET_RESOURCES_DATASOURCE_ID, DatasetResourcesRewriter.DATASET_RESOURCES, domain);
this.datasetId = datasetId;
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DumpIndexDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DumpIndexDatasource.java
index 04e3eea..6318f8e 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DumpIndexDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DumpIndexDatasource.java
@@ -39,7 +39,7 @@
public DumpIndexDatasource(INodeDomain domain, IndexDataflowHelperFactory indexDataflowHelperFactory,
RecordDescriptor recDesc, IBinaryComparatorFactory[] comparatorFactories) throws AlgebricksException {
- super(DUMP_INDEX_DATASOURCE_ID, domain);
+ super(DUMP_INDEX_DATASOURCE_ID, DumpIndexRewriter.DUMP_INDEX, domain);
this.indexDataflowHelperFactory = indexDataflowHelperFactory;
this.recDesc = recDesc;
this.comparatorFactories = comparatorFactories;
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/JobSummariesDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/JobSummariesDatasource.java
index 835a97d..6bab0cd 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/JobSummariesDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/JobSummariesDatasource.java
@@ -32,7 +32,7 @@
createDataSourceId(JobSummariesRewriter.JOBSUMMARIES);
public JobSummariesDatasource(INodeDomain domain) throws AlgebricksException {
- super(JOB_SUMMARIES_DATASOURCE_ID, domain);
+ super(JOB_SUMMARIES_DATASOURCE_ID, JobSummariesRewriter.JOBSUMMARIES, domain);
}
@Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/PingDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/PingDatasource.java
index 67d5e53..1b6d807 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/PingDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/PingDatasource.java
@@ -31,7 +31,7 @@
private static final DataSourceId PING_DATASOURCE_ID = createDataSourceId(PingRewriter.PING);
public PingDatasource(INodeDomain domain) throws AlgebricksException {
- super(PING_DATASOURCE_ID, domain);
+ super(PING_DATASOURCE_ID, PingRewriter.PING, domain);
}
@Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/StorageComponentsDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/StorageComponentsDatasource.java
index b8a4167..6157412 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/StorageComponentsDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/StorageComponentsDatasource.java
@@ -34,7 +34,7 @@
private final int datasetId;
public StorageComponentsDatasource(INodeDomain domain, int datasetId) throws AlgebricksException {
- super(STORAGE_COMPONENTS_DATASOURCE_ID, domain);
+ super(STORAGE_COMPONENTS_DATASOURCE_ID, StorageComponentsRewriter.STORAGE_COMPONENTS, domain);
this.datasetId = datasetId;
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSAllTablesDataGeneratorDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSAllTablesDataGeneratorDatasource.java
index c382fb4..82303fc 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSAllTablesDataGeneratorDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSAllTablesDataGeneratorDatasource.java
@@ -35,13 +35,11 @@
public class TPCDSAllTablesDataGeneratorDatasource extends FunctionDataSource {
private final double scalingFactor;
- private final FunctionIdentifier functionIdentifier;
TPCDSAllTablesDataGeneratorDatasource(INodeDomain domain, double scalingFactor,
FunctionIdentifier functionIdentifier) throws AlgebricksException {
- super(createDataSourceId(scalingFactor), domain);
+ super(createDataSourceId(scalingFactor), functionIdentifier, domain);
this.scalingFactor = scalingFactor;
- this.functionIdentifier = functionIdentifier;
}
/**
@@ -61,7 +59,7 @@
@Override
protected IDatasourceFunction createFunction(MetadataProvider metadataProvider,
AlgebricksAbsolutePartitionConstraint locations) {
- return new TPCDSDataGeneratorFunction(locations, null, scalingFactor, functionIdentifier);
+ return new TPCDSDataGeneratorFunction(locations, null, scalingFactor, functionId);
}
@Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSSingleTableDataGeneratorDatasource.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSSingleTableDataGeneratorDatasource.java
index df3903f..458bff6 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSSingleTableDataGeneratorDatasource.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/TPCDSSingleTableDataGeneratorDatasource.java
@@ -36,14 +36,12 @@
private final String tableName;
private final double scalingFactor;
- private final FunctionIdentifier functionIdentifier;
TPCDSSingleTableDataGeneratorDatasource(INodeDomain domain, String tableName, double scalingFactor,
FunctionIdentifier functionIdentifier) throws AlgebricksException {
- super(createDataSourceId(tableName, scalingFactor), domain);
+ super(createDataSourceId(tableName, scalingFactor), functionIdentifier, domain);
this.tableName = tableName;
this.scalingFactor = scalingFactor;
- this.functionIdentifier = functionIdentifier;
}
/**
@@ -65,7 +63,7 @@
@Override
protected IDatasourceFunction createFunction(MetadataProvider metadataProvider,
AlgebricksAbsolutePartitionConstraint locations) {
- return new TPCDSDataGeneratorFunction(locations, tableName, scalingFactor, functionIdentifier);
+ return new TPCDSDataGeneratorFunction(locations, tableName, scalingFactor, functionId);
}
@Override
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 46a3dc6..dd1f193 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
@@ -673,6 +673,8 @@
boolean bActiveTxn = true;
metadataProvider.setMetadataTxnContext(mdTxnCtx);
Dataset dataset = null;
+ Datatype itemTypeEntity = null, metaItemTypeEntity = null;
+ boolean itemTypeAdded = false, metaItemTypeAdded = false;
try {
// Check if the dataverse exists
Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, dataverseName);
@@ -690,8 +692,9 @@
throw new CompilationException(ErrorCode.DATASET_EXISTS, sourceLoc, datasetName, dataverseName);
}
}
- Datatype itemTypeEntity;
+
IAType itemType;
+ boolean itemTypeIsInline = false;
switch (itemTypeExpr.getTypeKind()) {
case TYPEREFERENCE:
itemTypeEntity = metadataProvider.findTypeEntity(itemTypeDataverseName, itemTypeName);
@@ -707,7 +710,7 @@
itemType = translateType(itemTypeDataverseName, itemTypeName, itemTypeExpr, mdTxnCtx);
validateDatasetItemType(dsType, itemType, false, sourceLoc);
itemTypeEntity = new Datatype(itemTypeDataverseName, itemTypeName, itemType, true);
- MetadataManager.INSTANCE.addDatatype(mdTxnCtx, itemTypeEntity);
+ itemTypeIsInline = true;
break;
default:
throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
@@ -723,13 +726,15 @@
} else {
validateCompactionPolicy(compactionPolicy, compactionPolicyProperties, mdTxnCtx, false, sourceLoc);
}
+
+ IAType metaItemType = null;
+ boolean metaItemTypeIsInline = false;
switch (dsType) {
case INTERNAL:
- IAType metaItemType = null;
if (metaItemTypeExpr != null) {
switch (metaItemTypeExpr.getTypeKind()) {
case TYPEREFERENCE:
- Datatype metaItemTypeEntity =
+ metaItemTypeEntity =
metadataProvider.findTypeEntity(metaItemTypeDataverseName, metaItemTypeName);
if (metaItemTypeEntity == null || metaItemTypeEntity.getIsAnonymous()) {
// anonymous types cannot be referred from CREATE DATASET
@@ -743,8 +748,9 @@
metaItemType = translateType(metaItemTypeDataverseName, metaItemTypeName,
metaItemTypeExpr, mdTxnCtx);
validateDatasetItemType(dsType, metaItemType, true, sourceLoc);
- MetadataManager.INSTANCE.addDatatype(mdTxnCtx,
- new Datatype(metaItemTypeDataverseName, metaItemTypeName, metaItemType, true));
+ metaItemTypeEntity =
+ new Datatype(metaItemTypeDataverseName, metaItemTypeName, metaItemType, true);
+ metaItemTypeIsInline = true;
break;
default:
throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
@@ -803,6 +809,16 @@
datasetDetails, dd.getHints(), dsType, DatasetIdFactory.generateDatasetId(),
MetadataUtil.PENDING_ADD_OP, compressionScheme);
MetadataManager.INSTANCE.addDataset(metadataProvider.getMetadataTxnContext(), dataset);
+
+ if (itemTypeIsInline) {
+ MetadataManager.INSTANCE.addDatatype(mdTxnCtx, itemTypeEntity);
+ itemTypeAdded = true;
+ }
+ if (metaItemTypeIsInline) {
+ MetadataManager.INSTANCE.addDatatype(mdTxnCtx, metaItemTypeEntity);
+ metaItemTypeAdded = true;
+ }
+
if (dsType == DatasetType.INTERNAL) {
JobSpecification jobSpec = DatasetUtil.createDatasetJobSpec(dataset, metadataProvider);
@@ -858,8 +874,15 @@
mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
metadataProvider.setMetadataTxnContext(mdTxnCtx);
try {
- MetadataManager.INSTANCE.dropDataset(metadataProvider.getMetadataTxnContext(), dataverseName,
- datasetName);
+ MetadataManager.INSTANCE.dropDataset(mdTxnCtx, dataverseName, datasetName);
+ if (itemTypeAdded) {
+ MetadataManager.INSTANCE.dropDatatype(mdTxnCtx, itemTypeEntity.getDataverseName(),
+ itemTypeEntity.getDatatypeName());
+ }
+ if (metaItemTypeAdded) {
+ MetadataManager.INSTANCE.dropDatatype(mdTxnCtx, metaItemTypeEntity.getDataverseName(),
+ metaItemTypeEntity.getDatatypeName());
+ }
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
} catch (Exception e2) {
e.addSuppressed(e2);
@@ -1664,38 +1687,9 @@
}
validateDatasetState(metadataProvider, ds, sourceLoc);
- // prepare to drop item and meta types if they were created as inline types
- DataverseName itemTypeDataverseName = ds.getItemTypeDataverseName();
- String itemTypeName = ds.getItemTypeName();
- boolean isInlineItemType = TypeUtil.isDatasetInlineTypeName(ds, itemTypeDataverseName, itemTypeName);
- if (isInlineItemType) {
- lockUtil.dropTypeBegin(lockManager, metadataProvider.getLocks(), itemTypeDataverseName, itemTypeName);
- }
- DataverseName metaTypeDataverseName = ds.getMetaItemTypeDataverseName();
- String metaTypeName = ds.getMetaItemTypeName();
- boolean isInlineMetaType =
- metaTypeName != null && TypeUtil.isDatasetInlineTypeName(ds, metaTypeDataverseName, metaTypeName);
- if (isInlineMetaType) {
- lockUtil.dropTypeBegin(lockManager, metadataProvider.getLocks(), metaTypeDataverseName, metaTypeName);
- }
- Datatype inlineItemType = isInlineItemType
- ? MetadataManager.INSTANCE.getDatatype(mdTxnCtx.getValue(), itemTypeDataverseName, itemTypeName)
- : null;
- Datatype inlineMetaType = isInlineMetaType
- ? MetadataManager.INSTANCE.getDatatype(mdTxnCtx.getValue(), metaTypeDataverseName, metaTypeName)
- : null;
-
ds.drop(metadataProvider, mdTxnCtx, jobsToExecute, bActiveTxn, progress, hcc, dropCorrespondingNodeGroup,
sourceLoc);
- // drop inline item and meta types
- if (isInlineItemType && inlineItemType.getIsAnonymous()) {
- MetadataManager.INSTANCE.dropDatatype(mdTxnCtx.getValue(), itemTypeDataverseName, itemTypeName);
- }
- if (isInlineMetaType && inlineMetaType.getIsAnonymous()) {
- MetadataManager.INSTANCE.dropDatatype(mdTxnCtx.getValue(), metaTypeDataverseName, metaTypeName);
- }
-
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx.getValue());
return true;
} catch (Exception e) {
@@ -2011,8 +2005,8 @@
}
protected void doCreateFunction(MetadataProvider metadataProvider, CreateFunctionStatement cfs,
- FunctionSignature signature, IStatementRewriter stmtRewriter) throws Exception {
- DataverseName dataverseName = signature.getDataverseName();
+ FunctionSignature functionSignature, IStatementRewriter stmtRewriter) throws Exception {
+ DataverseName dataverseName = functionSignature.getDataverseName();
SourceLocation sourceLoc = cfs.getSourceLocation();
MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
metadataProvider.setMetadataTxnContext(mdTxnCtx);
@@ -2021,45 +2015,85 @@
if (dv == null) {
throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverseName);
}
- Function function = MetadataManager.INSTANCE.getFunction(mdTxnCtx, signature);
- if (function != null) {
- if (cfs.getIfNotExists()) {
+ List<TypeSignature> existingInlineTypes;
+ Function existingFunction = MetadataManager.INSTANCE.getFunction(mdTxnCtx, functionSignature);
+ if (existingFunction != null) {
+ if (cfs.getReplaceIfExists()) {
+ if (cfs.getIfNotExists()) {
+ throw new CompilationException(ErrorCode.PARSE_ERROR, cfs.getSourceLocation(), "IF NOT EXISTS");
+ }
+ } else if (cfs.getIfNotExists()) {
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
return;
+ } else {
+ throw new CompilationException(ErrorCode.FUNCTION_EXISTS, cfs.getSourceLocation(),
+ functionSignature.toString(false));
}
- throw new CompilationException(ErrorCode.FUNCTION_EXISTS, cfs.getSourceLocation(),
- signature.toString(false));
+ existingInlineTypes = TypeUtil.getFunctionInlineTypes(existingFunction);
+ } else {
+ existingInlineTypes = Collections.emptyList();
}
- boolean isExternal = cfs.isExternal();
- List<Pair<VarIdentifier, TypeExpression>> paramList = cfs.getParameters();
- int paramCount = paramList.size();
- List<VarIdentifier> paramVars = new ArrayList<>(paramCount);
- List<String> paramNames = new ArrayList<>(paramCount);
- List<TypeSignature> paramTypes = new ArrayList<>(paramCount);
- LinkedHashSet<TypeSignature> dependentTypes = new LinkedHashSet<>();
+ Map<TypeSignature, Datatype> newInlineTypes;
+ Function function;
+ if (cfs.isExternal()) {
+ List<Pair<VarIdentifier, TypeExpression>> paramList = cfs.getParameters();
+ int paramCount = paramList.size();
+ List<String> paramNames = new ArrayList<>(paramCount);
+ List<TypeSignature> paramTypes = new ArrayList<>(paramCount);
+ LinkedHashSet<TypeSignature> depTypes = new LinkedHashSet<>();
+ newInlineTypes = new HashMap<>();
- for (int i = 0; i < paramCount; i++) {
- Pair<VarIdentifier, TypeExpression> paramPair = paramList.get(i);
- VarIdentifier paramName = paramPair.getFirst();
- TypeExpression paramTypeExpr = paramPair.getSecond();
- Pair<TypeSignature, TypeSignature> paramType = translateFunctionParameterType(signature, i,
- paramTypeExpr, isExternal, sourceLoc, metadataProvider, mdTxnCtx);
- paramVars.add(paramName);
- paramNames.add(stmtRewriter.toFunctionParameterName(paramName));
- paramTypes.add(paramType.first);
- if (paramType.second != null) {
- dependentTypes.add(paramType.second);
+ for (int i = 0; i < paramCount; i++) {
+ Pair<VarIdentifier, TypeExpression> paramPair = paramList.get(i);
+ TypeSignature paramTypeSignature;
+ TypeSignature paramDepTypeSignature;
+ Datatype paramInlineTypeEntity;
+ TypeExpression paramTypeExpr = paramPair.getSecond();
+ if (paramTypeExpr != null) {
+ Triple<TypeSignature, TypeSignature, Datatype> paramTypeInfo = translateFunctionParameterType(
+ functionSignature, i, paramTypeExpr, sourceLoc, metadataProvider, mdTxnCtx);
+ paramTypeSignature = paramTypeInfo.first;
+ paramDepTypeSignature = paramTypeInfo.second;
+ paramInlineTypeEntity = paramTypeInfo.third;
+ } else {
+ paramTypeSignature = null; // == any
+ paramDepTypeSignature = null;
+ paramInlineTypeEntity = null;
+ }
+ paramTypes.add(paramTypeSignature); // null == any
+ if (paramDepTypeSignature != null) {
+ depTypes.add(paramDepTypeSignature);
+ }
+ if (paramInlineTypeEntity != null) {
+ newInlineTypes.put(paramTypeSignature, paramInlineTypeEntity);
+ }
+ VarIdentifier paramName = paramPair.getFirst();
+ paramNames.add(stmtRewriter.toFunctionParameterName(paramName));
}
- }
- if (isExternal) {
+ TypeSignature returnTypeSignature;
+ TypeSignature returnDepTypeSignature;
+ Datatype returnInlineTypeEntity;
TypeExpression returnTypeExpr = cfs.getReturnType();
- Pair<TypeSignature, TypeSignature> returnType = translateFunctionParameterType(signature, -1,
- returnTypeExpr, isExternal, sourceLoc, metadataProvider, mdTxnCtx);
- if (returnType.second != null) {
- dependentTypes.add(returnType.second);
+ if (returnTypeExpr != null) {
+ Triple<TypeSignature, TypeSignature, Datatype> returnTypeInfo = translateFunctionParameterType(
+ functionSignature, -1, returnTypeExpr, sourceLoc, metadataProvider, mdTxnCtx);
+ returnTypeSignature = returnTypeInfo.first;
+ returnDepTypeSignature = returnTypeInfo.second;
+ returnInlineTypeEntity = returnTypeInfo.third;
+ } else {
+ returnTypeSignature = null; // == any
+ returnDepTypeSignature = null;
+ returnInlineTypeEntity = null;
}
+ if (returnDepTypeSignature != null) {
+ depTypes.add(returnDepTypeSignature);
+ }
+ if (returnInlineTypeEntity != null) {
+ newInlineTypes.put(returnTypeSignature, returnInlineTypeEntity);
+ }
+
DataverseName libraryDataverseName = cfs.getLibraryDataverseName();
if (libraryDataverseName == null) {
libraryDataverseName = dataverseName;
@@ -2075,14 +2109,28 @@
List<String> externalIdentifier = cfs.getExternalIdentifier();
ExternalFunctionCompilerUtil.validateExternalIdentifier(externalIdentifier, language,
cfs.getSourceLocation());
-
List<List<Triple<DataverseName, String, String>>> dependencies =
- FunctionUtil.getExternalFunctionDependencies(dependentTypes);
- function = new Function(signature, paramNames, paramTypes, returnType.first, null,
+ FunctionUtil.getExternalFunctionDependencies(depTypes);
+
+ function = new Function(functionSignature, paramNames, paramTypes, returnTypeSignature, null,
FunctionKind.SCALAR.toString(), library.getLanguage(), libraryDataverseName, libraryName,
externalIdentifier, cfs.getNullCall(), cfs.getDeterministic(), cfs.getResources(),
dependencies);
} else {
+ List<Pair<VarIdentifier, TypeExpression>> paramList = cfs.getParameters();
+ int paramCount = paramList.size();
+ List<VarIdentifier> paramVars = new ArrayList<>(paramCount);
+ List<String> paramNames = new ArrayList<>(paramCount);
+ for (Pair<VarIdentifier, TypeExpression> paramPair : paramList) {
+ VarIdentifier paramName = paramPair.getFirst();
+ paramVars.add(paramName);
+ paramNames.add(stmtRewriter.toFunctionParameterName(paramName));
+ if (paramPair.getSecond() != null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
+ paramName.toString());
+ }
+ }
+
//Check whether the function is use-able
metadataProvider.setDefaultDataverse(dv);
Query wrappedQuery = new Query(false);
@@ -2091,18 +2139,40 @@
wrappedQuery.setTopLevel(false);
apiFramework.reWriteQuery(declaredFunctions, metadataProvider, wrappedQuery, sessionOutput, false,
paramVars, warningCollector);
- List<List<Triple<DataverseName, String, String>>> dependencies =
- FunctionUtil.getFunctionDependencies(rewriterFactory.createQueryRewriter(),
- cfs.getFunctionBodyExpression(), metadataProvider, dependentTypes);
- function = new Function(signature, paramNames, paramTypes, TypeUtil.ANY_TYPE_SIGNATURE,
- cfs.getFunctionBody(), FunctionKind.SCALAR.toString(),
- compilationProvider.getParserFactory().getLanguage(), null, null, null, null, null, null,
- dependencies);
+ List<List<Triple<DataverseName, String, String>>> dependencies = FunctionUtil.getFunctionDependencies(
+ rewriterFactory.createQueryRewriter(), cfs.getFunctionBodyExpression(), metadataProvider);
+
+ newInlineTypes = Collections.emptyMap();
+ function = new Function(functionSignature, paramNames, null, null, cfs.getFunctionBody(),
+ FunctionKind.SCALAR.toString(), compilationProvider.getParserFactory().getLanguage(), null,
+ null, null, null, null, null, dependencies);
}
- MetadataManager.INSTANCE.addFunction(mdTxnCtx, function);
+ if (existingFunction == null) {
+ // add new function and its inline types
+ for (Datatype newInlineType : newInlineTypes.values()) {
+ MetadataManager.INSTANCE.addDatatype(mdTxnCtx, newInlineType);
+ }
+ MetadataManager.INSTANCE.addFunction(mdTxnCtx, function);
+ } else {
+ // replace existing function and its inline types
+ for (TypeSignature existingInlineType : existingInlineTypes) {
+ Datatype newInlineType =
+ newInlineTypes.isEmpty() ? null : newInlineTypes.remove(existingInlineType);
+ if (newInlineType == null) {
+ MetadataManager.INSTANCE.dropDatatype(mdTxnCtx, existingInlineType.getDataverseName(),
+ existingInlineType.getName());
+ } else {
+ MetadataManager.INSTANCE.updateDatatype(mdTxnCtx, newInlineType);
+ }
+ }
+ for (Datatype inlineType : newInlineTypes.values()) {
+ MetadataManager.INSTANCE.addDatatype(mdTxnCtx, inlineType);
+ }
+ MetadataManager.INSTANCE.updateFunction(mdTxnCtx, function);
+ }
if (LOGGER.isInfoEnabled()) {
- LOGGER.info("Installed function: " + signature);
+ LOGGER.info("Installed function: " + functionSignature);
}
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
} catch (Exception e) {
@@ -2111,20 +2181,11 @@
}
}
- private Pair<TypeSignature, TypeSignature> translateFunctionParameterType(FunctionSignature functionSignature,
- int paramIdx, TypeExpression paramTypeExpr, boolean isExternalFunction, SourceLocation sourceLoc,
+ private Triple<TypeSignature, TypeSignature, Datatype> translateFunctionParameterType(
+ FunctionSignature functionSignature, int paramIdx, TypeExpression paramTypeExpr, SourceLocation sourceLoc,
MetadataProvider metadataProvider, MetadataTransactionContext mdTxnCtx) throws AlgebricksException {
- if (paramTypeExpr == null) {
- return new Pair<>(TypeUtil.ANY_TYPE_SIGNATURE, null);
- }
-
- if (!isExternalFunction) {
- // grammar doesn't allow parameter types for inline functions
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc);
- }
-
- TypeSignature resultType, dependentType;
-
+ TypeSignature paramTypeSignature, depTypeSignature;
+ Datatype paramInlineTypeEntity = null;
switch (paramTypeExpr.getTypeKind()) {
case TYPEREFERENCE:
TypeReferenceExpression paramTypeRefExpr = (TypeReferenceExpression) paramTypeExpr;
@@ -2132,19 +2193,19 @@
BuiltinType builtinType = BuiltinTypeMap.getBuiltinType(paramTypeName);
if (builtinType != null) {
// built-in type
- resultType = new TypeSignature(builtinType);
- dependentType = null;
+ paramTypeSignature = new TypeSignature(builtinType);
+ depTypeSignature = null;
} else {
// user-defined type
DataverseName paramTypeDataverseName = paramTypeRefExpr.getIdent().first;
if (paramTypeDataverseName == null) {
paramTypeDataverseName = functionSignature.getDataverseName();
}
- IAType paramType = metadataProvider.findType(paramTypeDataverseName, paramTypeName);
- if (paramType == null) {
+ Datatype paramTypeEntity = metadataProvider.findTypeEntity(paramTypeDataverseName, paramTypeName);
+ if (paramTypeEntity == null || paramTypeEntity.getIsAnonymous()) {
throw new CompilationException(ErrorCode.UNKNOWN_TYPE, sourceLoc, paramTypeName);
}
- resultType = dependentType = new TypeSignature(paramTypeDataverseName, paramTypeName);
+ paramTypeSignature = depTypeSignature = new TypeSignature(paramTypeDataverseName, paramTypeName);
}
break;
case ORDEREDLIST:
@@ -2153,25 +2214,24 @@
paramTypeName = TypeUtil.createFunctionParameterTypeName(functionSignature.getName(),
functionSignature.getArity(), paramIdx);
IAType paramType = translateType(paramTypeDataverseName, paramTypeName, paramTypeExpr, mdTxnCtx);
- MetadataManager.INSTANCE.addDatatype(mdTxnCtx,
- new Datatype(paramTypeDataverseName, paramTypeName, paramType, true));
- resultType = new TypeSignature(paramTypeDataverseName, paramTypeName);
- dependentType = FunctionUtil.getTypeDependencyFromFunctionParameter(paramTypeExpr,
- functionSignature.getDataverseName());
+ paramTypeSignature = new TypeSignature(paramTypeDataverseName, paramTypeName);
+ depTypeSignature =
+ FunctionUtil.getTypeDependencyFromFunctionParameter(paramTypeExpr, paramTypeDataverseName);
+ paramInlineTypeEntity = new Datatype(paramTypeDataverseName, paramTypeName, paramType, true);
break;
default:
throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc);
}
- return new Pair<>(resultType, dependentType);
+ return new Triple<>(paramTypeSignature, depTypeSignature, paramInlineTypeEntity);
}
protected void handleFunctionDropStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
FunctionDropStatement stmtDropFunction = (FunctionDropStatement) stmt;
FunctionSignature signature = stmtDropFunction.getFunctionSignature();
- signature.setDataverseName(getActiveDataverseName(signature.getDataverseName()));
- lockUtil.dropFunctionBegin(lockManager, metadataProvider.getLocks(), signature.getDataverseName(),
- signature.getName());
+ DataverseName dataverseName = getActiveDataverseName(signature.getDataverseName());
+ signature.setDataverseName(dataverseName);
+ lockUtil.dropFunctionBegin(lockManager, metadataProvider.getLocks(), dataverseName, signature.getName());
try {
doDropFunction(metadataProvider, stmtDropFunction, signature);
} finally {
@@ -2181,18 +2241,18 @@
protected boolean doDropFunction(MetadataProvider metadataProvider, FunctionDropStatement stmtDropFunction,
FunctionSignature signature) throws Exception {
+ DataverseName dataverseName = signature.getDataverseName();
SourceLocation sourceLoc = stmtDropFunction.getSourceLocation();
MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
metadataProvider.setMetadataTxnContext(mdTxnCtx);
try {
- Dataverse dataverse = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, signature.getDataverseName());
+ Dataverse dataverse = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, dataverseName);
if (dataverse == null) {
if (stmtDropFunction.getIfExists()) {
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
return false;
} else {
- throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc,
- signature.getDataverseName());
+ throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverseName);
}
}
Function function = MetadataManager.INSTANCE.getFunction(mdTxnCtx, signature);
@@ -2201,11 +2261,16 @@
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
return false;
} else {
- throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, sourceLoc, signature.toString(false));
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, sourceLoc, signature.toString());
}
}
+ List<TypeSignature> inlineTypes = TypeUtil.getFunctionInlineTypes(function);
+
MetadataManager.INSTANCE.dropFunction(mdTxnCtx, signature);
+ for (TypeSignature inlineType : inlineTypes) {
+ MetadataManager.INSTANCE.dropDatatype(mdTxnCtx, inlineType.getDataverseName(), inlineType.getName());
+ }
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
return true;
} catch (Exception e) {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java
index 3b4f78f..55a1a80 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java
@@ -31,7 +31,6 @@
import org.apache.asterix.common.annotations.MissingNullInOutFunction;
import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.asterix.om.functions.FunctionInfo;
import org.apache.asterix.om.functions.IFunctionDescriptor;
import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
import org.apache.asterix.om.types.ATypeTag;
@@ -40,6 +39,7 @@
import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
import org.apache.asterix.runtime.functions.FunctionCollection;
import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
@@ -68,7 +68,7 @@
private static final Logger LOGGER = LogManager.getLogger();
// those are the functions that need IATypes of their args and use them in the function constructor
- private static Set<FunctionInfo> functionsRequiringTypes = new HashSet<>();
+ private static Set<FunctionIdentifier> functionsRequiringTypes = new HashSet<>();
@Parameters(name = "NullMissingTest {index}: {0}")
public static Collection<Object[]> tests() {
@@ -132,7 +132,7 @@
Pair<IScalarEvaluatorFactory[], IAType[]> argumentsAndTypesPair = argEvalFactoryIterator.next();
// Set the IAType if it's needed
- if (functionsRequiringTypes.contains(new FunctionInfo(funcDesc.getIdentifier(), true))) {
+ if (functionsRequiringTypes.contains(funcDesc.getIdentifier())) {
funcDesc.setImmutableStates((Object[]) argumentsAndTypesPair.second);
}
@@ -193,21 +193,21 @@
@BeforeClass
public static void buildFunctionsRequiringType() {
// Those are the functions that need IATypes of their args and use them in the function constructor
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.ARRAY_POSITION, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.ARRAY_CONTAINS, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.ARRAY_SORT, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.ARRAY_DISTINCT, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.ARRAY_EXCEPT, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.EQ, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.LT, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.GT, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.GE, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.LE, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.NEQ, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.MISSING_IF, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.NAN_IF, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.NEGINF_IF, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.NULL_IF, true));
- functionsRequiringTypes.add(new FunctionInfo(BuiltinFunctions.POSINF_IF, true));
+ functionsRequiringTypes.add(BuiltinFunctions.ARRAY_POSITION);
+ functionsRequiringTypes.add(BuiltinFunctions.ARRAY_CONTAINS);
+ functionsRequiringTypes.add(BuiltinFunctions.ARRAY_SORT);
+ functionsRequiringTypes.add(BuiltinFunctions.ARRAY_DISTINCT);
+ functionsRequiringTypes.add(BuiltinFunctions.ARRAY_EXCEPT);
+ functionsRequiringTypes.add(BuiltinFunctions.EQ);
+ functionsRequiringTypes.add(BuiltinFunctions.LT);
+ functionsRequiringTypes.add(BuiltinFunctions.GT);
+ functionsRequiringTypes.add(BuiltinFunctions.GE);
+ functionsRequiringTypes.add(BuiltinFunctions.LE);
+ functionsRequiringTypes.add(BuiltinFunctions.NEQ);
+ functionsRequiringTypes.add(BuiltinFunctions.MISSING_IF);
+ functionsRequiringTypes.add(BuiltinFunctions.NAN_IF);
+ functionsRequiringTypes.add(BuiltinFunctions.NEGINF_IF);
+ functionsRequiringTypes.add(BuiltinFunctions.NULL_IF);
+ functionsRequiringTypes.add(BuiltinFunctions.POSINF_IF);
}
}
diff --git a/asterixdb/asterix-app/src/test/resources/metadata/queries/basic/meta13/meta13.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/metadata/queries/basic/meta13/meta13.1.ddl.aql
index 52d7d19..8cf7085 100644
--- a/asterixdb/asterix-app/src/test/resources/metadata/queries/basic/meta13/meta13.1.ddl.aql
+++ b/asterixdb/asterix-app/src/test/resources/metadata/queries/basic/meta13/meta13.1.ddl.aql
@@ -17,7 +17,7 @@
* under the License.
*/
/*
- * Description : Create functions and drop that function and query metadata
+ * Description : Create functions and drop that function and query metadata
* : to verify entries in Function dataset for the dropped UDF.
* Expected Res : Success
* Date : Sep 17 2012
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 9df885d..a7ebb36 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": "any", "Definition": "\"This is an AQL Bodied UDF\"", "Language": "AQL", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ ] }
\ No newline at end of file
+{ "DataverseName": "testdv", "Name": "fun01", "Arity": "0", "Params": [ ], "ReturnType": "", "Definition": "\"This is an AQL Bodied UDF\"", "Language": "AQL", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.1.ddl.sqlpp
new file mode 100644
index 0000000..76cc70d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.1.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.10.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.10.query.sqlpp
new file mode 100644
index 0000000..58202fb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.10.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * 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 value {
+ "type": "eval",
+ "value": externallibtest.f2(3, 4)
+}
+union all
+select value {
+ "type": "meta-functions",
+ "value": ( select value m from Metadata.`Function` m where DataverseName = "externallibtest" )
+}
+union all
+select value {
+ "type": "meta-types",
+ "value": ( select value object_remove(m, "Timestamp") from Metadata.`Datatype` m where DataverseName = "externallibtest" )
+}
+order by `type`;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.11.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.11.ddl.sqlpp
new file mode 100644
index 0000000..66e94b1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.11.ddl.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.
+ */
+
+/*
+ * Test CREATE OR REPLACE FUNCTION.
+ * Replace with SQL++ function
+ */
+
+create or replace function externallibtest.f2(a, b) {
+ a * b
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.12.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.12.query.sqlpp
new file mode 100644
index 0000000..46f8b50
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.12.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * 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 value {
+ "type": "eval",
+ "value": externallibtest.f2(5, 6)
+}
+union all
+select value {
+ "type": "meta-functions",
+ "value": ( select value m from Metadata.`Function` m where DataverseName = "externallibtest" )
+}
+union all
+select value {
+ "type": "meta-types",
+ "value": ( select value object_remove(m, "Timestamp") from Metadata.`Datatype` m where DataverseName = "externallibtest" )
+}
+order by `type`;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.2.lib.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.2.lib.sqlpp
new file mode 100644
index 0000000..3dc6eb6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.2.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 admin admin target/data/externallib/asterix-external-data-testlib.zip
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.3.ddl.sqlpp
new file mode 100644
index 0000000..a16d594
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.3.ddl.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test default dataverse for the library reference
+ */
+
+create function externallibtest.f(a)
+ as "org.apache.asterix.external.library.OpenCapitalFinderFactory" at testlib;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.4.query.sqlpp
new file mode 100644
index 0000000..10772ec
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.4.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * 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 value {
+ "type": "eval",
+ "value": externallibtest.f("United States")
+}
+union all
+select value {
+ "type": "meta-functions",
+ "value": ( select value m from Metadata.`Function` m where DataverseName = "externallibtest" )
+}
+union all
+select value {
+ "type": "meta-types",
+ "value": ( select value object_remove(m, "Timestamp") from Metadata.`Datatype` m where DataverseName = "externallibtest" )
+}
+order by `type`;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.5.ddl.sqlpp
new file mode 100644
index 0000000..2727090
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.5.ddl.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test CREATE OR REPLACE FUNCTION.
+ *
+ * Replace implementation
+ * Replace parameter type.
+ */
+
+create or replace function externallibtest.f(a: [int32]) returns int32
+ as "org.apache.asterix.external.library.MyArraySumFactory" at testlib;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.6.query.sqlpp
new file mode 100644
index 0000000..34e8c26
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.6.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * 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 value {
+ "type": "eval",
+ "value": externallibtest.f([1, 2])
+}
+union all
+select value {
+ "type": "meta-functions",
+ "value": ( select value m from Metadata.`Function` m where DataverseName = "externallibtest" )
+}
+union all
+select value {
+ "type": "meta-types",
+ "value": ( select value object_remove(m, "Timestamp") from Metadata.`Datatype` m where DataverseName = "externallibtest" )
+}
+order by `type`;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.7.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.7.ddl.sqlpp
new file mode 100644
index 0000000..9276797
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.7.ddl.sqlpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test CREATE OR REPLACE FUNCTION.
+ *
+ * Replace implementation
+ * Replace parameter type with 'any'
+ * Replace return type with 'any'
+ */
+
+create or replace function externallibtest.f(a)
+ as "org.apache.asterix.external.library.OpenCapitalFinderFactory" at testlib;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.8.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.8.query.sqlpp
new file mode 100644
index 0000000..884c63d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.8.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * 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 value {
+ "type": "eval",
+ "value": externallibtest.f("Italy")
+}
+union all
+select value {
+ "type": "meta-functions",
+ "value": ( select value m from Metadata.`Function` m where DataverseName = "externallibtest" )
+}
+union all
+select value {
+ "type": "meta-types",
+ "value": ( select value object_remove(m, "Timestamp") from Metadata.`Datatype` m where DataverseName = "externallibtest" )
+}
+order by `type`;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.9.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.9.ddl.sqlpp
new file mode 100644
index 0000000..bd8d726
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/create-or-replace-function-1/create-or-replace-function-1.9.ddl.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.
+ */
+
+/*
+ * Test CREATE OR REPLACE FUNCTION.
+ *
+ * Create function with 2 parameters
+ */
+
+create function externallibtest.f2(a: int32, b: int32) returns int32
+ as "org.apache.asterix.external.library.MySumFactory" at testlib;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum_dropinuse/mysum_dropinuse.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum_dropinuse/mysum_dropinuse.5.ddl.sqlpp
index f8e2ae7..58447ec 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum_dropinuse/mysum_dropinuse.5.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum_dropinuse/mysum_dropinuse.5.ddl.sqlpp
@@ -18,4 +18,4 @@
*/
USE externallibtest;
-drop function externallibtest.mysum@2;
+drop function externallibtest.mysum(a: int32, b: int32);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-no-longer-used-by-feed/drop-function-no-longer-used-by-feed.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-no-longer-used-by-feed/drop-function-no-longer-used-by-feed.3.ddl.sqlpp
index c0ee51a..a92d8b7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-no-longer-used-by-feed/drop-function-no-longer-used-by-feed.3.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-no-longer-used-by-feed/drop-function-no-longer-used-by-feed.3.ddl.sqlpp
@@ -17,5 +17,4 @@
* under the License.
*/
use experiments;
-drop function test_func0@1;
-
+drop function test_func0@1;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-used-by-feed/drop-function-used-by-feed.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-used-by-feed/drop-function-used-by-feed.3.ddl.sqlpp
index c0ee51a..57d0a78 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-used-by-feed/drop-function-used-by-feed.3.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/feeds/drop-function-used-by-feed/drop-function-used-by-feed.3.ddl.sqlpp
@@ -17,5 +17,5 @@
* under the License.
*/
use experiments;
-drop function test_func0@1;
+drop function test_func0(x);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.2.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.2.ddl.sqlpp
index 14a68c0..e39a9fc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.2.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.2.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
use test;
-drop function test@0 if exists;
\ No newline at end of file
+drop function test() if exists;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.3.ddl.sqlpp
index 14a68c0..e39a9fc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.3.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/drop_if_exists/drop_if_exists.3.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
use test;
-drop function test@0 if exists;
\ No newline at end of file
+drop function test() if exists;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/default/default.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/default/default.3.ddl.sqlpp
index a0bc671..82bcc32 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/default/default.3.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/default/default.3.ddl.sqlpp
@@ -17,4 +17,4 @@
* under the License.
*/
-DROP function foo@0;
+DROP function foo();
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.1.ddl.sqlpp
new file mode 100644
index 0000000..c111196
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.1.ddl.sqlpp
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Test CREATE OR REPLACE FUNCTION
+ * Expected Res : Success
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+create function f1(a, b) {
+ a + b
+};
+
+/* Replace an existing function */
+create or replace function f1(a, b) {
+ a - b
+};
+
+/* Create new function */
+create or replace function f2(a, b) {
+ a * b
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.2.query.sqlpp
new file mode 100644
index 0000000..8e6c136
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.2.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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 test;
+
+{
+ "f1": f1(5, 2),
+ "f2": f2(5, 2)
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.3.query.sqlpp
new file mode 100644
index 0000000..7a19fc3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.3.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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 test;
+
+select f.Name, f.`Definition`
+from Metadata.`Function` f
+order by f.Name;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-3/drop-dependency.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-3/drop-dependency.3.ddl.sqlpp
index 7e7b60e..8e09034 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-3/drop-dependency.3.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-3/drop-dependency.3.ddl.sqlpp
@@ -39,4 +39,4 @@
};
use C;
-drop function f1@2;
\ No newline at end of file
+drop function f1(message, text);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-5/drop-dependency.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-5/drop-dependency.5.ddl.sqlpp
index 3a7f4dc..f301fc6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-5/drop-dependency.5.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-5/drop-dependency.5.ddl.sqlpp
@@ -35,4 +35,4 @@
C.f1(message,text)
};
-drop function f1@2;
\ No newline at end of file
+drop function f1(message, text);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.1.ddl.sqlpp
new file mode 100644
index 0000000..be5e07d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.1.ddl.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Test drop function
+ * Expected Res : Success
+ */
+
+drop dataverse experiments if exists;
+create dataverse experiments;
+use experiments;
+
+create function my_sum(a, b) {
+ a + b
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.2.query.sqlpp
new file mode 100644
index 0000000..0f0de1a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.2.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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 experiments;
+
+my_sum(2, 3);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.3.ddl.sqlpp
new file mode 100644
index 0000000..7023e16
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.3.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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 function experiments.my_sum(a, b);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.4.query.sqlpp
new file mode 100644
index 0000000..a998ac1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-function-1/drop-function-1.4.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.
+ */
+
+/*
+ * Description : Error. Unknown function
+ * Expected Res : Failure
+ */
+
+use experiments;
+
+my_sum(2, 3);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue455/query-issue455.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue455/query-issue455.4.ddl.sqlpp
index 8cb4580..d293b8e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue455/query-issue455.4.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue455/query-issue455.4.ddl.sqlpp
@@ -23,4 +23,4 @@
* Date : 19th May 2013
*/
-drop function test.printName@0;
+drop function test.printName();
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf33_overloading/udf33_overloading.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf33_overloading/udf33_overloading.1.ddl.sqlpp
new file mode 100644
index 0000000..670922d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf33_overloading/udf33_overloading.1.ddl.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Function overloading is allowed
+ * Expected Res : Success
+ */
+
+drop dataverse experiments if exists;
+create dataverse experiments;
+use experiments;
+
+create function myfn(a) {
+ a
+};
+
+create function myfn(a, b) {
+ a + b
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf33_overloading/udf33_overloading.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf33_overloading/udf33_overloading.2.query.sqlpp
new file mode 100644
index 0000000..c9359fc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/udf33_overloading/udf33_overloading.2.query.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Function overloading is allowed
+ * Expected Res : Success
+ */
+
+use experiments;
+
+{
+ "myfn_1": myfn(2),
+ "myfn_2": myfn(2, 3)
+}
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 ed83617..24d5071 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": "any" }
-{ "DataverseName": "testdv1", "Name": "fun02", "Arity": "1", "ReturnType": "any" }
-{ "DataverseName": "testdv1", "Name": "fun03", "Arity": "2", "ReturnType": "any" }
+{ "DataverseName": "testdv1", "Name": "fun01", "Arity": "0", "ReturnType": "" }
+{ "DataverseName": "testdv1", "Name": "fun02", "Arity": "1", "ReturnType": "" }
+{ "DataverseName": "testdv1", "Name": "fun03", "Arity": "2", "ReturnType": "" }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.10.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.10.adm
new file mode 100644
index 0000000..c0c9e29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.10.adm
@@ -0,0 +1,3 @@
+{ "type": "eval", "value": 7 }
+{ "type": "meta-functions", "value": [ { "DataverseName": "externallibtest", "Name": "f", "Arity": "1", "Params": [ "a" ], "ReturnType": "", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ null ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.OpenCapitalFinderFactory" ], "NullCall": false, "Deterministic": true }, { "DataverseName": "externallibtest", "Name": "f2", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "int32", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "int32" }, { "Type": "int32" } ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.MySumFactory" ], "NullCall": false, "Deterministic": true } ] }
+{ "type": "meta-types", "value": [ ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.12.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.12.adm
new file mode 100644
index 0000000..7775988
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.12.adm
@@ -0,0 +1,3 @@
+{ "type": "eval", "value": 30 }
+{ "type": "meta-functions", "value": [ { "DataverseName": "externallibtest", "Name": "f", "Arity": "1", "Params": [ "a" ], "ReturnType": "", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ null ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.OpenCapitalFinderFactory" ], "NullCall": false, "Deterministic": true }, { "DataverseName": "externallibtest", "Name": "f2", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "", "Definition": "a * b", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ] } ] }
+{ "type": "meta-types", "value": [ ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.4.adm
new file mode 100644
index 0000000..968097c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.4.adm
@@ -0,0 +1,3 @@
+{ "type": "eval", "value": { "country": "United States", "capital": "Washington D.C." } }
+{ "type": "meta-functions", "value": [ { "DataverseName": "externallibtest", "Name": "f", "Arity": "1", "Params": [ "a" ], "ReturnType": "", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ null ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.OpenCapitalFinderFactory" ], "NullCall": false, "Deterministic": true } ] }
+{ "type": "meta-types", "value": [ ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.6.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.6.adm
new file mode 100644
index 0000000..590b8de
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.6.adm
@@ -0,0 +1,3 @@
+{ "type": "eval", "value": 3 }
+{ "type": "meta-functions", "value": [ { "DataverseName": "externallibtest", "Name": "f", "Arity": "1", "Params": [ "a" ], "ReturnType": "int32", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "$f$t$f$1$0" } ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.MyArraySumFactory" ], "NullCall": false, "Deterministic": true } ] }
+{ "type": "meta-types", "value": [ { "DataverseName": "externallibtest", "DatatypeName": "$f$t$f$1$0", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "OrderedList": "int32" } } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.8.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.8.adm
new file mode 100644
index 0000000..4fda008
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/create-or-replace-function-1/create-or-replace-function-1.8.adm
@@ -0,0 +1,3 @@
+{ "type": "eval", "value": { "country": "Italy", "capital": "Rome" } }
+{ "type": "meta-functions", "value": [ { "DataverseName": "externallibtest", "Name": "f", "Arity": "1", "Params": [ "a" ], "ReturnType": "", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ null ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.OpenCapitalFinderFactory" ], "NullCall": false, "Deterministic": true } ] }
+{ "type": "meta-types", "value": [ ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm
index 51254a5..6d0ea72 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/udf_metadata/udf_metadata.3.adm
@@ -1,5 +1,5 @@
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn001", "Arity": "0", "Params": [ ], "ReturnType": "any", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.CapitalFinderFactory" ], "NullCall": false, "Deterministic": true } }
-{ "fn": { "DataverseName": "externallibtest", "Name": "myfn002", "Arity": "1", "Params": [ "a" ], "ReturnType": "any", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "any" } ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.CapitalFinderFactory" ], "NullCall": false, "Deterministic": true } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn001", "Arity": "0", "Params": [ ], "ReturnType": "", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.CapitalFinderFactory" ], "NullCall": false, "Deterministic": true } }
+{ "fn": { "DataverseName": "externallibtest", "Name": "myfn002", "Arity": "1", "Params": [ "a" ], "ReturnType": "", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ null ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.CapitalFinderFactory" ], "NullCall": false, "Deterministic": true } }
{ "fn": { "DataverseName": "externallibtest", "Name": "myfn003", "Arity": "3", "Params": [ "a", "b", "c" ], "ReturnType": "string", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "string" }, { "Type": "$f$t$myfn003$3$1" }, { "Type": "$f$t$myfn003$3$2" } ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.CapitalFinderFactory" ], "NullCall": false, "Deterministic": true } }
{ "fn": { "DataverseName": "externallibtest", "Name": "myfn004", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "CountryCapitalType", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ParamTypes": [ { "Type": "CountryCapitalType" }, { "Type": "$f$t$myfn004$2$1" } ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.CapitalFinderFactory" ], "NullCall": false, "Deterministic": true } }
{ "fn": { "DataverseName": "externallibtest", "Name": "myfn005", "Arity": "4", "Params": [ "a", "b", "c", "d" ], "ReturnType": "string", "Definition": "", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ [ "externallibtest", "CountryCapitalType" ] ] ], "ParamTypes": [ { "Type": "int16" }, { "Type": "$f$t$myfn005$4$1" }, { "Type": "CountryCapitalType" }, { "Type": "$f$t$myfn005$4$3" } ], "LibraryDataverseName": "externallibtest", "LibraryName": "testlib", "ExternalIdentifier": [ "org.apache.asterix.external.library.CapitalFinderFactory" ], "NullCall": false, "Deterministic": true } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.2.adm
new file mode 100644
index 0000000..e57f576
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.2.adm
@@ -0,0 +1 @@
+{ "f1": 3, "f2": 10 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.3.adm
new file mode 100644
index 0000000..63617d3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/create-or-replace-function-1/create-or-replace-function-1.3.adm
@@ -0,0 +1,2 @@
+{ "Name": "f1", "Definition": "a - b" }
+{ "Name": "f2", "Definition": "a * b" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/drop-function-1/drop-function-1.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/drop-function-1/drop-function-1.2.adm
new file mode 100644
index 0000000..7813681
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/drop-function-1/drop-function-1.2.adm
@@ -0,0 +1 @@
+5
\ No newline at end of file
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 10c6384..abd3c72 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": "any", "Definition": "'AsterixDB Shared nothing parallel BDMS'" }
\ No newline at end of file
+{ "DataverseName": "test", "Name": "printName", "Arity": "0", "ReturnType": "", "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 07e4942..eb1d4d6 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": "any", "Definition": "100" }
\ No newline at end of file
+{ "DataverseName": "test", "Name": "f1", "Arity": "0", "ReturnType": "", "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
index 07f3289..7cf89ce 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf32_metadata/udf32_metadata.2.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf32_metadata/udf32_metadata.2.adm
@@ -1,3 +1,3 @@
-{ "fn": { "DataverseName": "test", "Name": "myfn001", "Arity": "0", "Params": [ ], "ReturnType": "any", "Definition": "42", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn002", "Arity": "1", "Params": [ "a" ], "ReturnType": "any", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "any" } ] } }
-{ "fn": { "DataverseName": "test", "Name": "myfn003", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "any", "Definition": "a + b", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ], "ParamTypes": [ { "Type": "any" }, { "Type": "any" } ] } }
+{ "fn": { "DataverseName": "test", "Name": "myfn001", "Arity": "0", "Params": [ ], "ReturnType": "", "Definition": "42", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ] } }
+{ "fn": { "DataverseName": "test", "Name": "myfn002", "Arity": "1", "Params": [ "a" ], "ReturnType": "", "Definition": "a", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ] } }
+{ "fn": { "DataverseName": "test", "Name": "myfn003", "Arity": "2", "Params": [ "a", "b" ], "ReturnType": "", "Definition": "a + b", "Language": "SQLPP", "Kind": "SCALAR", "Dependencies": [ [ ], [ ], [ ] ] } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf33_overloading/udf33_overloading.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf33_overloading/udf33_overloading.2.adm
new file mode 100644
index 0000000..8024624
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/udf33_overloading/udf33_overloading.2.adm
@@ -0,0 +1 @@
+{ "myfn_1": 2, "myfn_2": 5 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_01/closed-record-constructor_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_01/closed-record-constructor_01.3.ast
index de7eb1a..bfe64db 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_01/closed-record-constructor_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_01/closed-record-constructor_01.3.ast
@@ -2,7 +2,7 @@
Set import-private-functions=true
Query:
SELECT ELEMENT [
-FunctionCall asterix.closed-object-constructor@8[
+FunctionCall asterix.closed-object-constructor[
LiteralExpr [STRING] [foo1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_02/closed-record-constructor_02.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_02/closed-record-constructor_02.3.ast
index f38fc1e..d158af6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_02/closed-record-constructor_02.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/closed-object-constructor_02/closed-record-constructor_02.3.ast
@@ -2,11 +2,11 @@
Set import-private-functions=true
Query:
SELECT ELEMENT [
-FunctionCall asterix.closed-object-constructor@8[
+FunctionCall asterix.closed-object-constructor[
LiteralExpr [STRING] [foo1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1]
- FunctionCall asterix.closed-object-constructor@12[
+ FunctionCall asterix.closed-object-constructor[
LiteralExpr [STRING] [bar1.1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1.2]
@@ -14,7 +14,7 @@
LiteralExpr [STRING] [bar1.3]
LiteralExpr [LONG] [30]
LiteralExpr [STRING] [bar1.4]
- FunctionCall asterix.closed-object-constructor@8[
+ FunctionCall asterix.closed-object-constructor[
LiteralExpr [STRING] [bar1.4.1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1.4.2]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_01/open-record-constructor_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_01/open-record-constructor_01.3.ast
index a94db4a..6dbabcb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_01/open-record-constructor_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_01/open-record-constructor_01.3.ast
@@ -2,7 +2,7 @@
Set import-private-functions=true
Query:
SELECT ELEMENT [
-FunctionCall asterix.open-object-constructor@8[
+FunctionCall asterix.open-object-constructor[
LiteralExpr [STRING] [foo1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_02/open-record-constructor_02.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_02/open-record-constructor_02.3.ast
index 0599ad9..c30e88f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_02/open-record-constructor_02.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/objects/open-object-constructor_02/open-record-constructor_02.3.ast
@@ -2,11 +2,11 @@
Set import-private-functions=true
Query:
SELECT ELEMENT [
-FunctionCall asterix.open-object-constructor@8[
+FunctionCall asterix.open-object-constructor[
LiteralExpr [STRING] [foo1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1]
- FunctionCall asterix.closed-object-constructor@12[
+ FunctionCall asterix.closed-object-constructor[
LiteralExpr [STRING] [bar1.1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1.2]
@@ -14,7 +14,7 @@
LiteralExpr [STRING] [bar1.3]
LiteralExpr [LONG] [30]
LiteralExpr [STRING] [bar1.4]
- FunctionCall asterix.closed-object-constructor@8[
+ FunctionCall asterix.closed-object-constructor[
LiteralExpr [STRING] [bar1.4.1]
LiteralExpr [LONG] [10]
LiteralExpr [STRING] [bar1.4.2]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
index d5f1993..86cd5b1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
@@ -116,7 +116,7 @@
]
Let Variable [ Name=$rank_result_actual ]
:=
- WINDOW asterix.rank-impl@-1[
+ WINDOW asterix.rank-impl[
]
AS Variable [ Name=#2 ]
(
@@ -165,7 +165,7 @@
]
Let Variable [ Name=$percent_rank_result_actual ]
:=
- WINDOW asterix.percent-rank-impl@-1[
+ WINDOW asterix.percent-rank-impl[
]
AS Variable [ Name=#3 ]
(
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 f5b4ede..ea5d279 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
@@ -24,6 +24,11 @@
<test-group name="external-library">
<test-case FilePath="external-library">
+ <compilation-unit name="create-or-replace-function-1">
+ <output-dir compare="Text">create-or-replace-function-1</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="external-library">
<compilation-unit name="type_validation">
<output-dir compare="Text">type_validation</output-dir>
</compilation-unit>
@@ -46,7 +51,7 @@
<test-case FilePath="external-library">
<compilation-unit name="mysum_dropinuse">
<output-dir compare="Text">mysum_dropinuse</output-dir>
- <expected-error>Cannot drop library externallibtest.testlib being used by funciton externallibtest.mysum@2</expected-error>
+ <expected-error>Cannot drop library externallibtest.testlib being used by funciton externallibtest.mysum(2)</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="external-library">
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 1495ce0..c37010c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -11764,48 +11764,59 @@
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
+ <compilation-unit name="create-or-replace-function-1">
+ <output-dir compare="Text">create-or-replace-function-1</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="user-defined-functions">
<compilation-unit name="drop-dependency-1">
<output-dir compare="Text">drop-dependency-1</output-dir>
- <expected-error>Cannot drop dataverse. Function B.f0@2 depends on function C.f1@2</expected-error>
+ <expected-error>Cannot drop dataverse. Function B.f0(2) depends on function C.f1(2)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
<compilation-unit name="drop-dependency-2">
<output-dir compare="Text">drop-dependency-2</output-dir>
- <expected-error>Cannot drop dataverse. Function B.f2@2 depends on dataset C.TweetMessages</expected-error>
+ <expected-error>Cannot drop dataverse. Function B.f2(2) depends on dataset C.TweetMessages</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
<compilation-unit name="drop-dependency-3">
<output-dir compare="Text">drop-dependency-3</output-dir>
- <expected-error>Cannot drop function C.f1@2 being used by function B.f0@2</expected-error>
+ <expected-error>Cannot drop function C.f1(2) being used by function B.f0(2)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
<compilation-unit name="drop-dependency-4">
<output-dir compare="Text">drop-dependency-4</output-dir>
- <expected-error>Cannot drop dataset C.TweetMessages being used by function B.f2@2</expected-error>
+ <expected-error>Cannot drop dataset C.TweetMessages being used by function B.f2(2)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
<compilation-unit name="drop-dependency-5">
<output-dir compare="Text">drop-dependency-5</output-dir>
- <expected-error>Cannot drop function C.f1@2 being used by function C.f0@2</expected-error>
+ <expected-error>Cannot drop function C.f1(2) being used by function C.f0(2)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
<compilation-unit name="drop-dependency-6">
<output-dir compare="Text">drop-dependency-6</output-dir>
- <expected-error>Cannot drop dataset C.TweetMessages being used by function C.f2@2</expected-error>
+ <expected-error>Cannot drop dataset C.TweetMessages being used by function C.f2(2)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
+ <compilation-unit name="drop-function-1">
+ <output-dir compare="Text">drop-function-1</output-dir>
+ <expected-error>ASX1081: Cannot find function with name experiments.my_sum</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="user-defined-functions">
<compilation-unit name="single-line-definition">
<output-dir compare="Text">single-line-definition</output-dir>
</compilation-unit>
@@ -12015,6 +12026,11 @@
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
+ <compilation-unit name="udf33_overloading">
+ <output-dir compare="Text">udf33_overloading</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>ASX1081: Cannot find function with name test.tinyint</expected-error>
@@ -12475,7 +12491,7 @@
<test-case FilePath="feeds">
<compilation-unit name="drop-function-used-by-feed">
<output-dir compare="Text">drop-function-used-by-feed</output-dir>
- <expected-error>Cannot drop function experiments.test_func0@1 being used by feed connection TwitterUsers.UserFeed</expected-error>
+ <expected-error>Cannot drop function experiments.test_func0(1) being used by feed connection TwitterUsers.UserFeed</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
@@ -12487,7 +12503,7 @@
<test-case FilePath="feeds">
<compilation-unit name="drop-dataverse-with-function-used-by-feed">
<output-dir compare="Text">drop-dataverse-with-function-used-by-feed</output-dir>
- <expected-error>Cannot drop dataverse. Feed connection feeddv.UserFeed depends on function fundv.test_func0@1</expected-error>
+ <expected-error>Cannot drop dataverse. Feed connection feeddv.UserFeed depends on function fundv.test_func0(1)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/functions/FunctionSignature.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/functions/FunctionSignature.java
index 0771645..1efdd42 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/functions/FunctionSignature.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/functions/FunctionSignature.java
@@ -51,8 +51,12 @@
return false;
}
FunctionSignature f = ((FunctionSignature) o);
- return Objects.equals(dataverseName, f.dataverseName) && name.equals(f.name)
- && (arity == f.arity || arity == FunctionIdentifier.VARARGS || f.arity == FunctionIdentifier.VARARGS);
+ return Objects.equals(dataverseName, f.dataverseName) && name.equals(f.name) && arity == f.arity;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(dataverseName, name, arity);
}
@Override
@@ -64,23 +68,29 @@
boolean dataverseNameExists = dataverseName != null;
String dataverseCanonicalName = dataverseNameExists ? dataverseName.getCanonicalForm() : null;
int len = (dataverseNameExists ? dataverseCanonicalName.length() + 1 : 0) + name.length()
- + (includeArity ? 3 : 0);
+ + (includeArity ? 5 : 0);
StringBuilder sb = new StringBuilder(len);
if (dataverseNameExists) {
sb.append(dataverseCanonicalName).append('.');
}
sb.append(name);
if (includeArity) {
- sb.append('@').append(arity);
+ sb.append('(');
+ switch (arity) {
+ case FunctionIdentifier.VARARGS:
+ sb.append("...");
+ break;
+ case 0:
+ break;
+ default:
+ sb.append(arity);
+ break;
+ }
+ sb.append(')');
}
return sb.toString();
}
- @Override
- public int hashCode() {
- return Objects.hash(dataverseName, name);
- }
-
public DataverseName getDataverseName() {
return dataverseName;
}
@@ -109,15 +119,11 @@
return createFunctionIdentifier(dataverseName, name, arity);
}
- public static FunctionIdentifier createFunctionIdentifier(DataverseName dataverseName, String functionName,
+ private static FunctionIdentifier createFunctionIdentifier(DataverseName dataverseName, String functionName,
int arity) {
return new FunctionIdentifier(dataverseName.getCanonicalForm(), functionName, arity);
}
- public static FunctionIdentifier createFunctionIdentifier(DataverseName dataverseName, String functionName) {
- return new FunctionIdentifier(dataverseName.getCanonicalForm(), functionName);
- }
-
public static DataverseName getDataverseName(FunctionIdentifier fi) {
String dataverseCanonicalName = fi.getNamespace();
switch (dataverseCanonicalName) {
diff --git a/asterixdb/asterix-doc/src/main/markdown/sqlpp/5_ddl_function_removal.md b/asterixdb/asterix-doc/src/main/markdown/sqlpp/5_ddl_function_removal.md
index 34b611f..a0742a3 100644
--- a/asterixdb/asterix-doc/src/main/markdown/sqlpp/5_ddl_function_removal.md
+++ b/asterixdb/asterix-doc/src/main/markdown/sqlpp/5_ddl_function_removal.md
@@ -22,7 +22,7 @@
The CREATE FUNCTION statement creates a **named** function that can then be used and reused in queries.
The body of a function can be any query expression involving the function's parameters.
- FunctionSpecification ::= "FUNCTION" FunctionOrTypeName IfNotExists ParameterList "{" Expression "}"
+ FunctionSpecification ::= (<OR> <REPLACE>)? "FUNCTION" FunctionOrTypeName IfNotExists ParameterList "{" Expression "}"
The following is an example of a CREATE FUNCTION statement which is similar to our earlier DECLARE FUNCTION example.
It differs from that example in that it results in a function that is persistently registered by name in the specified dataverse (the current dataverse being used, if not otherwise specified).
@@ -35,9 +35,19 @@
WHERE u.id = userId)[0]
};
+The following is an example of CREATE FUNCTION statement that replaces an existing function.
+
+##### Example
+
+ CREATE OR REPLACE FUNCTION friendInfo(userId) {
+ (SELECT u.id, u.name
+ FROM GleambookUsers u
+ WHERE u.id = userId)[0]
+ };
+
### <a id="Synonyms"> Synonyms</a>
- SynonymSpecification ::= "SYNONYM" QualifiedName "FOR" QualifiedName IfNotExists
+ SynonymSpecification ::= "SYNONYM" QualifiedName IfNotExists "FOR" QualifiedName
The CREATE SYNONYM statement creates a synonym for a given dataset.
This synonym may be used used instead of the dataset name in SELECT, INSERT, UPSERT, DELETE, and LOAD statements.
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/visitor/AqlFunctionCallResolverVisitor.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/visitor/AqlFunctionCallResolverVisitor.java
index 71c26f2..32f368b 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/visitor/AqlFunctionCallResolverVisitor.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/visitor/AqlFunctionCallResolverVisitor.java
@@ -33,7 +33,7 @@
import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.metadata.declared.MetadataProvider;
-public final class AqlFunctionCallResolverVisitor extends AbstractAqlSimpleExpressionVisitor {
+public class AqlFunctionCallResolverVisitor extends AbstractAqlSimpleExpressionVisitor {
private final MetadataProvider metadataProvider;
@@ -44,7 +44,7 @@
public AqlFunctionCallResolverVisitor(MetadataProvider metadataProvider, List<FunctionDecl> declaredFunctions) {
this.metadataProvider = metadataProvider;
this.declaredFunctions = FunctionUtil.getFunctionSignatures(declaredFunctions);
- this.callExprResolver = FunctionUtil.createBuiltinFunctionResolver(metadataProvider);
+ this.callExprResolver = createBuiltinFunctionResolver(metadataProvider);
}
@Override
@@ -54,4 +54,9 @@
callExpr.setFunctionSignature(fs);
return super.visit(callExpr, arg);
}
+
+ protected BiFunction<String, Integer, FunctionSignature> createBuiltinFunctionResolver(
+ MetadataProvider metadataProvider) {
+ return FunctionUtil.createBuiltinFunctionResolver(metadataProvider);
+ }
}
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/base/AbstractAqlSimpleExpressionVisitor.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/base/AbstractAqlSimpleExpressionVisitor.java
index b8c3470..e23eec9 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/base/AbstractAqlSimpleExpressionVisitor.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/base/AbstractAqlSimpleExpressionVisitor.java
@@ -50,6 +50,7 @@
import org.apache.asterix.lang.common.expression.UnaryExpr;
import org.apache.asterix.lang.common.expression.VariableExpr;
import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.InsertStatement;
import org.apache.asterix.lang.common.statement.Query;
import org.apache.asterix.lang.common.struct.QuantifiedPair;
@@ -215,6 +216,17 @@
return null;
}
+ @Override
+ public Expression visit(InsertStatement insertStatement, ILangExpression arg) throws CompilationException {
+ Expression returnExpr = insertStatement.getReturnExpression();
+ if (returnExpr != null) {
+ insertStatement.setReturnExpression(visit(returnExpr, arg));
+ }
+ Query bodyQuery = insertStatement.getQuery();
+ bodyQuery.accept(this, arg);
+ return null;
+ }
+
protected Expression visit(Expression expr, ILangExpression arg) throws CompilationException {
return postVisit(preVisit(expr).accept(this, arg));
}
diff --git a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
index 67816c5..35a7a92 100644
--- a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
+++ b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
@@ -759,7 +759,7 @@
for(VarIdentifier v: paramList){
bodge.add(new Pair<VarIdentifier,TypeExpression>(v,null));
}
- return new CreateFunctionStatement(signature, bodge, functionBody, functionBodyExpr, ifNotExists);
+ return new CreateFunctionStatement(signature, bodge, functionBody, functionBodyExpr, false, ifNotExists);
}
}
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 2e8a937..baaa2c1 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
@@ -52,7 +52,6 @@
private final FunctionSignature signature;
private final String functionBody;
private final Expression functionBodyExpression;
- private final boolean ifNotExists;
private final List<Pair<VarIdentifier, TypeExpression>> paramList;
private final TypeExpression returnType;
@@ -61,26 +60,29 @@
private final List<String> externalIdentifier;
private final AdmObjectNode options;
+ private final boolean replaceIfExists;
+ private final boolean ifNotExists;
+
public CreateFunctionStatement(FunctionSignature signature, List<Pair<VarIdentifier, TypeExpression>> paramList,
- String functionBody, Expression functionBodyExpression, boolean ifNotExists) {
+ String functionBody, Expression functionBodyExpression, boolean replaceIfExists, boolean ifNotExists) {
this.signature = signature;
this.functionBody = functionBody;
this.functionBodyExpression = functionBodyExpression;
- this.ifNotExists = ifNotExists;
this.paramList = requireNullTypes(paramList); // parameter type specification is not allowed for inline functions
this.returnType = null; // return type specification is not allowed for inline functions
this.libraryDataverseName = null;
this.libraryName = null;
this.externalIdentifier = null;
this.options = null;
+ this.replaceIfExists = replaceIfExists;
+ this.ifNotExists = ifNotExists;
}
public CreateFunctionStatement(FunctionSignature signature, List<Pair<VarIdentifier, TypeExpression>> paramList,
TypeExpression returnType, DataverseName libraryDataverseName, String libraryName,
- List<String> externalIdentifier, RecordConstructor options, boolean ifNotExists)
+ List<String> externalIdentifier, RecordConstructor options, boolean replaceIfExists, boolean ifNotExists)
throws CompilationException {
this.signature = signature;
- this.ifNotExists = ifNotExists;
this.paramList = paramList;
this.returnType = returnType;
this.libraryDataverseName = libraryDataverseName;
@@ -89,6 +91,12 @@
this.options = options == null ? null : ExpressionUtils.toNode(options);
this.functionBody = null;
this.functionBodyExpression = null;
+ this.replaceIfExists = replaceIfExists;
+ this.ifNotExists = ifNotExists;
+ }
+
+ public boolean getReplaceIfExists() {
+ return replaceIfExists;
}
public boolean getIfNotExists() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java
index 0496ecc..2c59ea9 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java
@@ -27,7 +27,7 @@
public class FunctionDropStatement extends AbstractStatement {
private final FunctionSignature signature;
- private boolean ifExists;
+ private final boolean ifExists;
public FunctionDropStatement(FunctionSignature signature, boolean ifExists) {
this.signature = signature;
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 60c1c3d..71cd759 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
@@ -46,6 +46,7 @@
import org.apache.asterix.metadata.entities.BuiltinTypeMap;
import org.apache.asterix.metadata.entities.Dataverse;
import org.apache.asterix.metadata.entities.Function;
+import org.apache.asterix.om.functions.BuiltinFunctionInfo;
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.TypeSignature;
@@ -55,9 +56,7 @@
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
import org.apache.hyracks.api.exceptions.SourceLocation;
public class FunctionUtil {
@@ -69,21 +68,11 @@
private static final String FN_DATASET_NAME = BuiltinFunctions.DATASET.getName();
- public static IFunctionInfo getFunctionInfo(FunctionIdentifier fi) {
- return BuiltinFunctions.getAsterixFunctionInfo(fi);
- }
-
- public static IFunctionInfo getFunctionInfo(FunctionSignature fs) {
- return getFunctionInfo(fs.createFunctionIdentifier());
- }
-
- public static IFunctionInfo getBuiltinFunctionInfo(String functionName, int arity) {
- IFunctionInfo fi =
- getFunctionInfo(new FunctionIdentifier(AlgebricksBuiltinFunctions.ALGEBRICKS_NS, functionName, arity));
- if (fi == null) {
- fi = getFunctionInfo(new FunctionIdentifier(FunctionConstants.ASTERIX_NS, functionName, arity));
- }
- return fi;
+ /**
+ * @deprecated use {@link BuiltinFunctions#getBuiltinFunctionInfo(FunctionIdentifier)} instead
+ */
+ public static BuiltinFunctionInfo getFunctionInfo(FunctionIdentifier fi) {
+ return BuiltinFunctions.getBuiltinFunctionInfo(fi);
}
public static TypeSignature getTypeDependencyFromFunctionParameter(TypeExpression typeExpr,
@@ -174,11 +163,21 @@
public static BiFunction<String, Integer, FunctionSignature> createBuiltinFunctionResolver(
MetadataProvider metadataProvider) {
boolean includePrivateFunctions = getImportPrivateFunctions(metadataProvider);
+ return createBuiltinFunctionResolver(includePrivateFunctions);
+ }
+
+ public static BiFunction<String, Integer, FunctionSignature> createBuiltinFunctionResolver(
+ boolean includePrivateFunctions) {
return (name, arity) -> {
String builtinName = name.replace('_', '-');
- FunctionIdentifier builtinId =
- BuiltinFunctions.getBuiltinCompilerFunction(builtinName, arity, includePrivateFunctions);
- return builtinId != null ? new FunctionSignature(builtinId) : null;
+ BuiltinFunctionInfo finfo = BuiltinFunctions.resolveBuiltinFunction(builtinName, arity);
+ if (finfo == null) {
+ return null;
+ }
+ if (!includePrivateFunctions && finfo.isPrivate()) {
+ return null;
+ }
+ return new FunctionSignature(finfo.getFunctionIdentifier());
};
}
@@ -244,13 +243,11 @@
}
public static List<List<Triple<DataverseName, String, String>>> getFunctionDependencies(IQueryRewriter rewriter,
- Expression expression, MetadataProvider metadataProvider, Collection<TypeSignature> dependentTypes)
- throws CompilationException {
+ Expression expression, MetadataProvider metadataProvider) throws CompilationException {
Set<CallExpr> functionCalls = rewriter.getFunctionCalls(expression);
//Get the List of used functions and used datasets
List<Triple<DataverseName, String, String>> datasourceDependencies = new ArrayList<>();
List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
- List<Triple<DataverseName, String, String>> typeDependencies = new ArrayList<>(dependentTypes.size());
for (CallExpr functionCall : functionCalls) {
FunctionSignature signature = functionCall.getFunctionSignature();
if (isBuiltinDatasetFunction(signature)) {
@@ -258,18 +255,15 @@
metadataProvider.getDefaultDataverseName(), functionCall.getSourceLocation(),
ExpressionUtils::getStringLiteral);
datasourceDependencies.add(new Triple<>(datasetReference.first, datasetReference.second, null));
- } else if (!BuiltinFunctions.isBuiltinCompilerFunction(signature, false)) {
+ } else if (BuiltinFunctions.getBuiltinFunctionInfo(signature.createFunctionIdentifier()) == null) {
functionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
Integer.toString(signature.getArity())));
}
}
- for (TypeSignature t : dependentTypes) {
- typeDependencies.add(new Triple<>(t.getDataverseName(), t.getName(), null));
- }
List<List<Triple<DataverseName, String, String>>> dependencies = new ArrayList<>(3);
dependencies.add(datasourceDependencies);
dependencies.add(functionDependencies);
- dependencies.add(typeDependencies);
+ dependencies.add(Collections.emptyList());
return dependencies;
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
index 3a329cc..325f9b0 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
@@ -787,7 +787,7 @@
@Override
public Void visit(CreateFunctionStatement cfs, Integer step) throws CompilationException {
- out.print(skip(step) + CREATE + " function ");
+ out.print(skip(step) + CREATE + generateOrReplace(cfs.getReplaceIfExists()) + " function ");
out.print(generateIfNotExists(cfs.getIfNotExists()));
out.print(this.generateFullName(cfs.getFunctionSignature().getDataverseName(),
cfs.getFunctionSignature().getName()));
@@ -1042,6 +1042,10 @@
return ifExits ? " if exists" : "";
}
+ protected String generateOrReplace(boolean orReplace) {
+ return orReplace ? " or replace" : "";
+ }
+
protected String generateIndexTypeString(IndexType type) {
switch (type) {
case BTREE:
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
index f83a89e..90fb9c1 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
@@ -163,7 +163,7 @@
return null;
}
- private static void printFunctionSignature(PrintWriter out, FunctionSignature fs, int arity) {
+ protected static void printFunctionSignature(PrintWriter out, FunctionSignature fs, int arity) {
out.print(fs.toString(false));
if (arity != FunctionIdentifier.VARARGS) {
out.print("@");
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 7339a08..3c98a2d 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
@@ -178,13 +178,20 @@
// Inlines functions.
inlineDeclaredUdfs(inlineUdfs);
- // Inlines WITH expressions after variableCheckAndRewrite(...) so that the variable scoping for WITH
- // expression is correct.
- inlineWithExpressions();
-
// Rewrites SQL++ core aggregate function names into internal names
rewriteSpecialFunctionNames();
+ // Inlines WITH expressions after variableCheckAndRewrite(...) so that the variable scoping for WITH
+ // expression is correct.
+ //
+ // Must run after rewriteSpecialFunctionNames() because it needs to have FunctionInfo
+ // for all functions to avoid inlining non-deterministic expressions.
+ // (CallExprs with special function names do not have FunctionInfo)
+ //
+ // Must run after inlineDeclaredUdfs() because we only maintain deterministic modifiers for built-in
+ // and external UDFs, therefore need to inline SQL++ UDFs to check the deterministic property.
+ inlineWithExpressions();
+
// Sets the var counter of the query.
topStatement.setVarCounter(context.getVarCounter().get());
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java
index bae21e4..d6ee1fc 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java
@@ -23,10 +23,10 @@
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppContainsExpressionVisitor;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.Function;
+import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
@@ -44,19 +44,26 @@
@Override
public Boolean visit(CallExpr callExpr, Void arg) throws CompilationException {
FunctionSignature fs = callExpr.getFunctionSignature();
- IFunctionInfo fi = FunctionUtil.getBuiltinFunctionInfo(fs.getName(), fs.getArity());
- if (fi != null) {
- if (!fi.isFunctional()) {
+ IFunctionInfo finfo = BuiltinFunctions.getBuiltinFunctionInfo(fs.createFunctionIdentifier());
+ if (finfo != null) {
+ if (!finfo.isFunctional()) {
return true;
}
} else {
+ Function function;
try {
- Function function = metadataProvider.lookupUserDefinedFunction(fs);
- if (function != null && function.getDeterministic() != null && !function.getDeterministic()) {
- return true;
- }
+ function = metadataProvider.lookupUserDefinedFunction(fs);
} catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.METADATA_ERROR, e, callExpr.getSourceLocation());
+ throw new CompilationException(ErrorCode.METADATA_ERROR, e, callExpr.getSourceLocation(), e.toString());
+ }
+ if (function == null || function.getDeterministic() == null) {
+ // fail if function not found because all functions must have been resolved at this point
+ // fail if function does not define deterministic property (because it's a SQL++ function
+ // and they were supposed to be inlined at this point)
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, callExpr.getSourceLocation(), fs);
+ }
+ if (!function.getDeterministic()) {
+ return true;
}
}
return super.visit(callExpr, arg);
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
index 9c5c1a4..038be3e 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
@@ -359,7 +359,9 @@
@Override
public Void visit(WindowExpression winExpr, Integer step) throws CompilationException {
- out.println(skip(step) + "WINDOW " + winExpr.getFunctionSignature() + "[");
+ out.print(skip(step) + "WINDOW ");
+ printFunctionSignature(out, winExpr.getFunctionSignature(), winExpr.getFunctionSignature().getArity());
+ out.println("[");
for (Expression expr : winExpr.getExprList()) {
expr.accept(this, step + 1);
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 5cdf1a7..525c15e 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -233,6 +233,7 @@
private static final String SETS = "SETS";
private static final String TIES = "TIES";
private static final String UNBOUNDED = "UNBOUNDED";
+ private static final String REPLACE = "REPLACE";
private static final String RETURNS = "RETURNS";
private static final String INT_TYPE_NAME = "int";
@@ -464,12 +465,20 @@
}
private boolean isToken(String image) {
+ return isToken(token, image);
+ }
+
+ private static boolean isToken(Token token, String image) {
return token.image.equalsIgnoreCase(image);
}
private void expectToken(String image) throws SqlppParseException {
- if (!isToken(image)) {
- throw createUnexpectedTokenError();
+ expectToken(token, image);
+ }
+
+ private static void expectToken(Token token, String image) throws SqlppParseException {
+ if (!isToken(token, image)) {
+ throw createUnexpectedTokenError(token);
}
}
@@ -477,7 +486,7 @@
return createUnexpectedTokenError(token, null);
}
- private SqlppParseException createUnexpectedTokenError(Token t) {
+ private static SqlppParseException createUnexpectedTokenError(Token t) {
return createUnexpectedTokenError(t, null);
}
@@ -485,7 +494,7 @@
return createUnexpectedTokenError(token, expected);
}
- private SqlppParseException createUnexpectedTokenError(Token t, String expected) {
+ private static SqlppParseException createUnexpectedTokenError(Token t, String expected) {
String message = "Unexpected token: " + LogRedactionUtil.userData(t.image) +
(expected == null ? "" : ". Expected: " + LogRedactionUtil.userData(expected));
return new SqlppParseException(getSourceLocation(t), message);
@@ -652,12 +661,13 @@
{
<CREATE> { startToken = token; }
(
- stmt = CreateTypeStatement(startToken)
+ stmt = CreateOrReplaceStatement(startToken)
+ | stmt = CreateTypeStatement(startToken)
| stmt = CreateNodegroupStatement(startToken)
| stmt = CreateDatasetStatement(startToken)
| stmt = CreateIndexStatement(startToken)
| stmt = CreateDataverseStatement(startToken)
- | stmt = CreateFunctionStatement(startToken)
+ | stmt = CreateFunctionStatement(startToken, false)
| stmt = CreateAdapterStatement(startToken)
| stmt = CreateSynonymStatement(startToken)
| stmt = CreateFeedStatement(startToken)
@@ -668,6 +678,23 @@
}
}
+Statement CreateOrReplaceStatement(Token startStmtToken) throws ParseException:
+{
+ Statement stmt = null;
+ Token replaceToken = null;
+}
+{
+ <OR> <IDENTIFIER> { replaceToken = token; }
+ (
+ stmt = CreateFunctionStatement(startStmtToken, true)
+ )
+ {
+ // check expected token here to make the grammar extension plugin happy
+ expectToken(replaceToken, REPLACE);
+ return stmt;
+ }
+}
+
TypeDecl CreateTypeStatement(Token startStmtToken) throws ParseException:
{
TypeDecl stmt = null;
@@ -1120,18 +1147,18 @@
}
}
-CreateFunctionStatement CreateFunctionStatement(Token startStmtToken) throws ParseException:
+CreateFunctionStatement CreateFunctionStatement(Token startStmtToken, boolean orReplace) throws ParseException:
{
CreateFunctionStatement stmt = null;
}
{
- <FUNCTION> stmt = FunctionSpecification(startStmtToken)
+ <FUNCTION> stmt = FunctionSpecification(startStmtToken, orReplace)
{
return stmt;
}
}
-CreateFunctionStatement FunctionSpecification(Token startStmtToken) throws ParseException:
+CreateFunctionStatement FunctionSpecification(Token startStmtToken, boolean orReplace) throws ParseException:
{
FunctionSignature signature = null;
FunctionName fctName = null;
@@ -1172,7 +1199,7 @@
removeCurrentScope();
defaultDataverse = currentDataverse;
ensureNoTypeDeclsInFunction(fctName.function, params, returnType, startStmtToken);
- stmt = new CreateFunctionStatement(signature, params, functionBody, functionBodyExpr, ifNotExists);
+ stmt = new CreateFunctionStatement(signature, params, functionBody, functionBodyExpr, orReplace, ifNotExists);
return addSourceLocation(stmt, startStmtToken);
}
)
@@ -1186,7 +1213,7 @@
defaultDataverse = currentDataverse;
try {
stmt = new CreateFunctionStatement(signature, params, returnType, libraryName.first,
- libraryName.second.getValue(), externalIdentifier, withOptions, ifNotExists);
+ libraryName.second.getValue(), externalIdentifier, withOptions, orReplace, ifNotExists);
} catch (AlgebricksException e) {
throw new SqlppParseException(getSourceLocation(startStmtToken), e.getMessage());
}
@@ -1340,7 +1367,6 @@
}
}
-
CreateSynonymStatement CreateSynonymStatement(Token startStmtToken) throws ParseException:
{
CreateSynonymStatement stmt = null;
@@ -1417,20 +1443,38 @@
FunctionSignature FunctionSignature() throws ParseException:
{
FunctionName fctName = null;
+ List<Pair<VarIdentifier,TypeExpression>> params = null;
int arity = 0;
}
{
- fctName = FunctionName() <ATT> <INTEGER_LITERAL>
- {
- arity = new Integer(token.image);
- if (arity < 0 && arity != FunctionIdentifier.VARARGS) {
- throw new SqlppParseException(getSourceLocation(token), "Invalid arity:" + arity);
- }
+ fctName = FunctionName()
+ (
+ LOOKAHEAD(2) params = FunctionParameters() { arity = params.size(); }
+ | ( <LEFTPAREN> arity = FunctionArity() <RIGHTPAREN> )
+ | ( <ATT> arity = FunctionArity() ) // back-compat
+ )
+ {
+ return new FunctionSignature(fctName.dataverse, fctName.function, arity);
+ }
+}
- // TODO use fctName.library
- String fqFunctionName = fctName.library == null ? fctName.function : fctName.library + "#" + fctName.function;
- return new FunctionSignature(fctName.dataverse, fqFunctionName, arity);
+int FunctionArity() throws ParseException:
+{
+ int arity;
+}
+{
+ <INTEGER_LITERAL>
+ {
+ try {
+ arity = Integer.parseInt(token.image);
+ } catch (NumberFormatException e) {
+ throw new SqlppParseException(getSourceLocation(token), "Invalid arity: " + token.image);
}
+ if (arity < 0 && arity != FunctionIdentifier.VARARGS) {
+ throw new SqlppParseException(getSourceLocation(token), "Invalid arity: " + arity);
+ }
+ return arity;
+ }
}
Pair<List<Integer>, List<List<String>>> PrimaryKey() throws ParseException:
diff --git a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/main/java/org/apache/asterix/extension/grammar/GrammarExtensionMojo.java b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/main/java/org/apache/asterix/extension/grammar/GrammarExtensionMojo.java
index 52b2be5..d47e9a6 100644
--- a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/main/java/org/apache/asterix/extension/grammar/GrammarExtensionMojo.java
+++ b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/main/java/org/apache/asterix/extension/grammar/GrammarExtensionMojo.java
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.LineNumberReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -324,7 +325,7 @@
}
String innerBlock2String = null;
if (baseBlocks.second != null) {
- BufferedReader blockReader = stringToReader(baseBlocks.second);
+ LineNumberReader blockReader = stringToReader(baseBlocks.second);
Position blockPosition = new Position();
blockPosition.index = 0;
blockPosition.line = blockReader.readLine();
@@ -337,7 +338,8 @@
blockPosition.line = blockReader.readLine();
}
if (blockPosition.line == null) {
- throw new MojoExecutionException(errorMessage);
+ throw new MojoExecutionException(errorMessage + " at line " + blockReader.getLineNumber() + " of "
+ + StringUtils.abbreviate(baseBlocks.second, 100));
}
int block2Open = blockPosition.line.indexOf(OPEN_BRACE);
blockPosition.line = blockPosition.line.substring(block2Open + 1);
@@ -350,7 +352,8 @@
blockPosition.line = blockReader.readLine();
}
if (blockPosition.line == null) {
- throw new MojoExecutionException(errorMessage);
+ throw new MojoExecutionException(errorMessage + " at line " + blockReader.getLineNumber() + " of "
+ + StringUtils.abbreviate(baseBlocks.second, 100));
}
int innerBlock1Open = blockPosition.line.indexOf(OPEN_PAREN);
writer.write(" ");
@@ -372,7 +375,8 @@
}
int innerBlock2Open = blockPosition.line.indexOf(OPEN_BRACE);
if (innerBlock2Open < 0) {
- throw new MojoExecutionException(errorMessage);
+ throw new MojoExecutionException(errorMessage + " at line " + blockReader.getLineNumber() + " of "
+ + StringUtils.abbreviate(baseBlocks.second, 100));
}
blockPosition.index = innerBlock2Open;
readBlock(blockReader, OPEN_BRACE, CLOSE_BRACE, blockPosition);
@@ -989,9 +993,9 @@
}
}
- private BufferedReader stringToReader(String aString) {
+ private LineNumberReader stringToReader(String aString) {
InputStream is = new ByteArrayInputStream(aString.getBytes(StandardCharsets.UTF_8));
- return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+ return new LineNumberReader(new InputStreamReader(is, StandardCharsets.UTF_8));
}
private File prepareOutputFile() throws MojoExecutionException {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
index afc0dc5..268a9c0 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
@@ -576,7 +576,7 @@
public Function getFunction(MetadataTransactionContext ctx, FunctionSignature functionSignature)
throws AlgebricksException {
// First look in the context to see if this transaction created the
- // requested dataset itself (but the dataset is still uncommitted).
+ // requested function itself (but the function is still uncommitted).
Function function = ctx.getFunction(functionSignature);
if (function != null) {
// Don't add this dataverse to the cache, since it is still
@@ -984,6 +984,30 @@
}
@Override
+ public void updateFunction(MetadataTransactionContext ctx, Function function) throws AlgebricksException {
+ try {
+ metadataNode.updateFunction(ctx.getTxnId(), function);
+ } catch (RemoteException e) {
+ throw new MetadataException(ErrorCode.REMOTE_EXCEPTION_WHEN_CALLING_METADATA_NODE, e);
+ }
+ // reflect the function into the cache
+ ctx.dropFunction(function.getSignature());
+ ctx.addFunction(function);
+ }
+
+ @Override
+ public void updateDatatype(MetadataTransactionContext ctx, Datatype datatype) throws AlgebricksException {
+ try {
+ metadataNode.updateDatatype(ctx.getTxnId(), datatype);
+ } catch (RemoteException e) {
+ throw new MetadataException(ErrorCode.REMOTE_EXCEPTION_WHEN_CALLING_METADATA_NODE, e);
+ }
+ // reflect the datatype into the cache
+ ctx.dropDataDatatype(datatype.getDataverseName(), datatype.getDatatypeName());
+ ctx.addDatatype(datatype);
+ }
+
+ @Override
public <T extends IExtensionMetadataEntity> void addEntity(MetadataTransactionContext mdTxnCtx, T entity)
throws AlgebricksException {
try {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
index 07dd4e5..88098f8 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
@@ -86,6 +86,7 @@
import org.apache.asterix.metadata.entitytupletranslators.NodeTupleTranslator;
import org.apache.asterix.metadata.entitytupletranslators.SynonymTupleTranslator;
import org.apache.asterix.metadata.utils.DatasetUtil;
+import org.apache.asterix.metadata.utils.TypeUtil;
import org.apache.asterix.metadata.valueextractors.MetadataEntityValueExtractor;
import org.apache.asterix.metadata.valueextractors.TupleCopyValueExtractor;
import org.apache.asterix.om.base.AInt32;
@@ -433,15 +434,12 @@
// Insert into the 'function' dataset.
FunctionTupleTranslator tupleReaderWriter =
tupleTranslatorProvider.getFunctionTupleTranslator(txnId, this, true);
-
ITupleReference functionTuple = tupleReaderWriter.getTupleFromMetadataEntity(function);
insertTupleIntoIndex(txnId, MetadataPrimaryIndexes.FUNCTION_DATASET, functionTuple);
-
} catch (HyracksDataException e) {
if (e.getComponent().equals(ErrorCode.HYRACKS) && e.getErrorCode() == ErrorCode.DUPLICATE_KEY) {
- throw new AlgebricksException("A function with this name " + function.getName() + " and arity "
- + function.getArity() + " already exists in dataverse '" + function.getDataverseName() + "'.",
- e);
+ throw new AlgebricksException("A function with this name " + function.getSignature()
+ + " already exists in dataverse '" + function.getDataverseName() + "'.", e);
} else {
throw new AlgebricksException(e);
}
@@ -547,8 +545,7 @@
// As a side effect, acquires an S lock on the 'Function' dataset on behalf of txnId.
List<Function> dataverseFunctions = getDataverseFunctions(txnId, dataverseName);
for (Function function : dataverseFunctions) {
- dropFunction(txnId, new FunctionSignature(dataverseName, function.getName(), function.getArity()),
- true);
+ dropFunction(txnId, function.getSignature(), true);
}
// Drop all adapters in this dataverse.
@@ -721,9 +718,14 @@
@Override
public void dropDatatype(TxnId txnId, DataverseName dataverseName, String datatypeName) throws AlgebricksException {
+ dropDatatype(txnId, dataverseName, datatypeName, false);
+ }
- confirmDatatypeIsUnused(txnId, dataverseName, datatypeName);
-
+ private void dropDatatype(TxnId txnId, DataverseName dataverseName, String datatypeName, boolean force)
+ throws AlgebricksException {
+ if (!force) {
+ confirmDatatypeIsUnused(txnId, dataverseName, datatypeName);
+ }
// Delete the datatype entry, including all it's nested anonymous types.
try {
ITupleReference searchKey = createTuple(dataverseName, datatypeName);
@@ -888,16 +890,7 @@
}
public List<Function> getAllFunctions(TxnId txnId) throws AlgebricksException {
- try {
- FunctionTupleTranslator tupleReaderWriter =
- tupleTranslatorProvider.getFunctionTupleTranslator(txnId, this, false);
- IValueExtractor<Function> valueExtractor = new MetadataEntityValueExtractor<>(tupleReaderWriter);
- List<Function> results = new ArrayList<>();
- searchIndex(txnId, MetadataPrimaryIndexes.FUNCTION_DATASET, null, valueExtractor, results);
- return results;
- } catch (HyracksDataException e) {
- throw new AlgebricksException(e);
- }
+ return getFunctionsImpl(txnId, null);
}
public List<Datatype> getAllDatatypes(TxnId txnId) throws AlgebricksException {
@@ -949,15 +942,16 @@
continue;
}
if (set.getItemTypeDataverseName().equals(dataverseName)) {
- throw new AlgebricksException(
- "Cannot drop dataverse. Type " + dataverseName + "." + set.getItemTypeName()
- + " used by dataset " + set.getDataverseName() + "." + set.getDatasetName());
+ throw new AlgebricksException("Cannot drop dataverse. Type "
+ + TypeUtil.getFullyQualifiedDisplayName(set.getItemTypeDataverseName(), set.getItemTypeName())
+ + " used by dataset " + DatasetUtil.getFullyQualifiedDisplayName(set));
}
if (set.getMetaItemTypeDataverseName() != null
&& set.getMetaItemTypeDataverseName().equals(dataverseName)) {
- throw new AlgebricksException(
- "Cannot drop dataverse. Type " + dataverseName + "." + set.getMetaItemTypeName()
- + " used by dataset " + set.getDataverseName() + "." + set.getDatasetName());
+ throw new AlgebricksException("Cannot drop dataverse. Type "
+ + TypeUtil.getFullyQualifiedDisplayName(set.getMetaItemTypeDataverseName(),
+ set.getMetaItemTypeName())
+ + " used by dataset " + DatasetUtil.getFullyQualifiedDisplayName(set));
}
}
@@ -971,24 +965,22 @@
}
for (Triple<DataverseName, String, String> datasetDependency : function.getDependencies().get(0)) {
if (datasetDependency.first.equals(dataverseName)) {
- throw new AlgebricksException("Cannot drop dataverse. Function " + function.getDataverseName() + "."
- + function.getName() + "@" + function.getArity() + " depends on dataset "
- + datasetDependency.first + "." + datasetDependency.second);
+ throw new AlgebricksException("Cannot drop dataverse. Function " + function.getSignature()
+ + " depends on dataset " + DatasetUtil.getFullyQualifiedDisplayName(datasetDependency.first,
+ datasetDependency.second));
}
}
for (Triple<DataverseName, String, String> functionDependency : function.getDependencies().get(1)) {
if (functionDependency.first.equals(dataverseName)) {
- throw new AlgebricksException(
- "Cannot drop dataverse. Function " + function.getDataverseName() + "." + function.getName()
- + "@" + function.getArity() + " depends on function " + functionDependency.first
- + "." + functionDependency.second + "@" + functionDependency.third);
+ throw new AlgebricksException("Cannot drop dataverse. Function " + function.getSignature()
+ + " depends on function " + new FunctionSignature(functionDependency.first,
+ functionDependency.second, Integer.parseInt(functionDependency.third)));
}
}
for (Triple<DataverseName, String, String> type : function.getDependencies().get(2)) {
if (type.first.equals(dataverseName)) {
- throw new AlgebricksException(
- "Cannot drop dataverse. Function " + function.getDataverseName() + "." + function.getName()
- + "@" + function.getArity() + " depends on type " + type.first + "." + type.second);
+ throw new AlgebricksException("Cannot drop dataverse. Function " + function.getSignature()
+ + " depends on type " + TypeUtil.getFullyQualifiedDisplayName(type.first, type.second));
}
}
}
@@ -1002,10 +994,9 @@
}
for (FunctionSignature functionSignature : feedConnection.getAppliedFunctions()) {
if (dataverseName.equals(functionSignature.getDataverseName())) {
- throw new AlgebricksException("Cannot drop dataverse. Feed connection "
- + feedConnection.getDataverseName() + "." + feedConnection.getFeedName()
- + " depends on function " + functionSignature.getDataverseName() + "."
- + functionSignature.getName() + "@" + functionSignature.getArity());
+ throw new AlgebricksException(
+ "Cannot drop dataverse. Feed connection " + feedConnection.getDataverseName() + "."
+ + feedConnection.getFeedName() + " depends on function " + functionSignature);
}
}
}
@@ -1019,8 +1010,8 @@
if (functionalDependency.first.equals(signature.getDataverseName())
&& functionalDependency.second.equals(signature.getName())
&& functionalDependency.third.equals(Integer.toString(signature.getArity()))) {
- throw new AlgebricksException("Cannot drop function " + signature + " being used by function "
- + function.getDataverseName() + "." + function.getName() + "@" + function.getArity());
+ throw new AlgebricksException(
+ "Cannot drop function " + signature + " being used by function " + function.getSignature());
}
}
}
@@ -1044,8 +1035,7 @@
if (datasetDependency.first.equals(dataverseName) && datasetDependency.second.equals(datasetName)) {
throw new AlgebricksException("Cannot drop dataset "
+ DatasetUtil.getFullyQualifiedDisplayName(dataverseName, datasetName)
- + " being used by function " + function.getDataverseName() + "." + function.getName() + "@"
- + function.getArity());
+ + " being used by function " + function.getSignature());
}
}
}
@@ -1063,9 +1053,8 @@
for (Function function : functions) {
if (libraryName.equals(function.getLibraryName())
&& dataverseName.equals(function.getLibraryDataverseName())) {
- throw new AlgebricksException(
- "Cannot drop library " + dataverseName + '.' + libraryName + " being used by funciton "
- + function.getDataverseName() + '.' + function.getName() + '@' + function.getArity());
+ throw new AlgebricksException("Cannot drop library " + dataverseName + '.' + libraryName
+ + " being used by funciton " + function.getSignature());
}
}
}
@@ -1096,8 +1085,9 @@
List<Dataset> datasets = getAllDatasets(txnId);
for (Dataset set : datasets) {
if (set.getItemTypeName().equals(datatypeName) && set.getItemTypeDataverseName().equals(dataverseName)) {
- throw new AlgebricksException("Cannot drop type " + dataverseName + "." + datatypeName
- + " being used by dataset " + set.getDataverseName() + "." + set.getDatasetName());
+ throw new AlgebricksException(
+ "Cannot drop type " + TypeUtil.getFullyQualifiedDisplayName(dataverseName, datatypeName)
+ + " being used by dataset " + DatasetUtil.getFullyQualifiedDisplayName(set));
}
}
}
@@ -1119,8 +1109,9 @@
}
AbstractComplexType recType = (AbstractComplexType) dataType.getDatatype();
if (recType.containsType(typeToBeDropped)) {
- throw new AlgebricksException("Cannot drop type " + dataverseName + "." + datatypeName
- + " being used by type " + dataverseName + "." + recType.getTypeName());
+ throw new AlgebricksException("Cannot drop type "
+ + TypeUtil.getFullyQualifiedDisplayName(dataverseName, datatypeName) + " being used by type "
+ + TypeUtil.getFullyQualifiedDisplayName(dataverseName, recType.getTypeName()));
}
}
}
@@ -1132,9 +1123,9 @@
for (Function function : functions) {
for (Triple<DataverseName, String, String> datasetDependency : function.getDependencies().get(2)) {
if (datasetDependency.first.equals(dataverseName) && datasetDependency.second.equals(dataTypeName)) {
- throw new AlgebricksException("Cannot drop type " + dataverseName + "." + dataTypeName
- + " is being used by function " + function.getDataverseName() + "." + function.getName()
- + "@" + function.getArity());
+ throw new AlgebricksException(
+ "Cannot drop type " + TypeUtil.getFullyQualifiedDisplayName(dataverseName, dataTypeName)
+ + " is being used by function " + function.getSignature());
}
}
}
@@ -1253,27 +1244,18 @@
@Override
public Function getFunction(TxnId txnId, FunctionSignature functionSignature) throws AlgebricksException {
- try {
- ITupleReference searchKey = createTuple(functionSignature.getDataverseName(), functionSignature.getName(),
- Integer.toString(functionSignature.getArity()));
- FunctionTupleTranslator tupleReaderWriter =
- tupleTranslatorProvider.getFunctionTupleTranslator(txnId, this, false);
- List<Function> results = new ArrayList<>();
- IValueExtractor<Function> valueExtractor = new MetadataEntityValueExtractor<>(tupleReaderWriter);
- searchIndex(txnId, MetadataPrimaryIndexes.FUNCTION_DATASET, searchKey, valueExtractor, results);
- if (results.isEmpty()) {
- return null;
- }
- return results.get(0);
- } catch (HyracksDataException e) {
- throw new AlgebricksException(e);
- }
+ List<Function> functions = getFunctionsImpl(txnId, createTuple(functionSignature.getDataverseName(),
+ functionSignature.getName(), Integer.toString(functionSignature.getArity())));
+ return functions.isEmpty() ? null : functions.get(0);
}
@Override
public List<Function> getDataverseFunctions(TxnId txnId, DataverseName dataverseName) throws AlgebricksException {
+ return getFunctionsImpl(txnId, createTuple(dataverseName));
+ }
+
+ private List<Function> getFunctionsImpl(TxnId txnId, ITupleReference searchKey) throws AlgebricksException {
try {
- ITupleReference searchKey = createTuple(dataverseName);
FunctionTupleTranslator tupleReaderWriter =
tupleTranslatorProvider.getFunctionTupleTranslator(txnId, this, false);
List<Function> results = new ArrayList<>();
@@ -1295,25 +1277,19 @@
if (!force) {
confirmFunctionCanBeDeleted(txnId, functionSignature);
}
- Function function = getFunction(txnId, functionSignature);
- if (function == null) {
- throw new AlgebricksException(
- "Cannot drop function '" + functionSignature.toString() + "' because it doesn't exist.");
- }
try {
// Delete entry from the 'function' dataset.
ITupleReference searchKey = createTuple(functionSignature.getDataverseName(), functionSignature.getName(),
Integer.toString(functionSignature.getArity()));
- // Searches the index for the tuple to be deleted. Acquires an S
- // lock on the 'function' dataset.
+ // Searches the index for the tuple to be deleted. Acquires an S lock on the 'function' dataset.
ITupleReference functionTuple =
getTupleToBeDeleted(txnId, MetadataPrimaryIndexes.FUNCTION_DATASET, searchKey);
deleteTupleFromIndex(txnId, MetadataPrimaryIndexes.FUNCTION_DATASET, functionTuple);
} catch (HyracksDataException e) {
if (e.getComponent().equals(ErrorCode.HYRACKS)
&& e.getErrorCode() == ErrorCode.UPDATE_OR_DELETE_NON_EXISTENT_KEY) {
- throw new AlgebricksException("There is no function with the name " + functionSignature.getName()
- + " and arity " + functionSignature.getArity(), e);
+ throw new AlgebricksException(
+ "Cannot drop function '" + functionSignature + "' because it doesn't exist", e);
} else {
throw new AlgebricksException(e);
}
@@ -1661,7 +1637,6 @@
LibraryTupleTranslator tupleReaderWriter = tupleTranslatorProvider.getLibraryTupleTranslator(true);
ITupleReference libraryTuple = tupleReaderWriter.getTupleFromMetadataEntity(library);
insertTupleIntoIndex(txnId, MetadataPrimaryIndexes.LIBRARY_DATASET, libraryTuple);
-
} catch (HyracksDataException e) {
if (e.getComponent().equals(ErrorCode.HYRACKS) && e.getErrorCode() == ErrorCode.DUPLICATE_KEY) {
throw new AlgebricksException("A library with this name " + library.getDataverseName()
@@ -1674,13 +1649,18 @@
@Override
public void dropLibrary(TxnId txnId, DataverseName dataverseName, String libraryName) throws AlgebricksException {
- confirmLibraryCanBeDeleted(txnId, dataverseName, libraryName);
+ dropLibrary(txnId, dataverseName, libraryName, false);
+ }
+ private void dropLibrary(TxnId txnId, DataverseName dataverseName, String libraryName, boolean force)
+ throws AlgebricksException {
+ if (!force) {
+ confirmLibraryCanBeDeleted(txnId, dataverseName, libraryName);
+ }
try {
// Delete entry from the 'Library' dataset.
ITupleReference searchKey = createTuple(dataverseName, libraryName);
- // Searches the index for the tuple to be deleted. Acquires an S
- // lock on the 'Adapter' dataset.
+ // Searches the index for the tuple to be deleted. Acquires an S lock on the 'Library' dataset.
ITupleReference datasetTuple =
getTupleToBeDeleted(txnId, MetadataPrimaryIndexes.LIBRARY_DATASET, searchKey);
deleteTupleFromIndex(txnId, MetadataPrimaryIndexes.LIBRARY_DATASET, datasetTuple);
@@ -2101,40 +2081,41 @@
// This method will delete previous entry of the dataset and insert the new one
// Delete entry from the 'datasets' dataset.
ITupleReference searchKey = createTuple(dataset.getDataverseName(), dataset.getDatasetName());
- // Searches the index for the tuple to be deleted. Acquires an S
- // lock on the 'dataset' dataset.
+ // Searches the index for the tuple to be deleted. Acquires an S lock on the 'dataset' dataset.
ITupleReference datasetTuple =
getTupleToBeDeleted(txnId, MetadataPrimaryIndexes.DATASET_DATASET, searchKey);
deleteTupleFromIndex(txnId, MetadataPrimaryIndexes.DATASET_DATASET, datasetTuple);
- // Previous tuple was deleted
// Insert into the 'dataset' dataset.
DatasetTupleTranslator tupleReaderWriter = tupleTranslatorProvider.getDatasetTupleTranslator(true);
datasetTuple = tupleReaderWriter.getTupleFromMetadataEntity(dataset);
insertTupleIntoIndex(txnId, MetadataPrimaryIndexes.DATASET_DATASET, datasetTuple);
} catch (HyracksDataException e) {
- throw new AlgebricksException(e);
+ if (e.getComponent().equals(ErrorCode.HYRACKS)
+ && e.getErrorCode() == ErrorCode.UPDATE_OR_DELETE_NON_EXISTENT_KEY) {
+ throw new AlgebricksException(
+ "Cannot drop dataset '" + dataset.getDatasetName() + "' because it doesn't exist");
+ } else {
+ throw new AlgebricksException(e);
+ }
}
}
@Override
public void updateLibrary(TxnId txnId, Library library) throws AlgebricksException {
- try {
- // This method will delete previous entry of the library and insert the new one
- // Delete entry from the 'library' dataset.
- ITupleReference searchKey = createTuple(library.getDataverseName(), library.getName());
- // Searches the index for the tuple to be deleted. Acquires an S
- // lock on the 'library' dataset.
- ITupleReference libraryTuple =
- getTupleToBeDeleted(txnId, MetadataPrimaryIndexes.LIBRARY_DATASET, searchKey);
- deleteTupleFromIndex(txnId, MetadataPrimaryIndexes.LIBRARY_DATASET, libraryTuple);
- // Previous tuple was deleted
- // Insert into the 'library' dataset.
- LibraryTupleTranslator tupleReaderWriter = tupleTranslatorProvider.getLibraryTupleTranslator(true);
- libraryTuple = tupleReaderWriter.getTupleFromMetadataEntity(library);
- insertTupleIntoIndex(txnId, MetadataPrimaryIndexes.LIBRARY_DATASET, libraryTuple);
- } catch (HyracksDataException e) {
- throw new AlgebricksException(e);
- }
+ dropLibrary(txnId, library.getDataverseName(), library.getName(), true);
+ addLibrary(txnId, library);
+ }
+
+ @Override
+ public void updateFunction(TxnId txnId, Function function) throws AlgebricksException {
+ dropFunction(txnId, function.getSignature(), true);
+ addFunction(txnId, function);
+ }
+
+ @Override
+ public void updateDatatype(TxnId txnId, Datatype datatype) throws AlgebricksException {
+ dropDatatype(txnId, datatype.getDataverseName(), datatype.getDatatypeName(), true);
+ addDatatype(txnId, datatype);
}
public ITxnIdFactory getTxnIdFactory() {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataManager.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataManager.java
index da4d2fb..1646a93 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataManager.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataManager.java
@@ -723,6 +723,24 @@
void updateLibrary(MetadataTransactionContext ctx, Library library) throws AlgebricksException;
/**
+ * @param mdTxnCtx
+ * MetadataTransactionContext of an active metadata transaction.
+ * @param function
+ * An instance of type Function that represents the function being
+ * updated
+ */
+ void updateFunction(MetadataTransactionContext mdTxnCtx, Function function) throws AlgebricksException;
+
+ /**
+ * @param mdTxnCtx
+ * MetadataTransactionContext of an active metadata transaction.
+ * @param datatype
+ * An instance of type Datatype that represents the datatype being
+ * updated
+ */
+ void updateDatatype(MetadataTransactionContext mdTxnCtx, Datatype datatype) throws AlgebricksException;
+
+ /**
* Add an extension entity to its extension dataset under the ongoing metadata
* transaction
*
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java
index 6a450f2..bca4171 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java
@@ -824,6 +824,28 @@
void updateLibrary(TxnId txnId, Library library) throws AlgebricksException, RemoteException;
/**
+ * update an existing function in the metadata, acquiring local locks on behalf
+ * of the given transaction id.
+ *
+ * @param txnId
+ * A globally unique id for an active metadata transaction.
+ * @param function
+ * updated Function instance.
+ */
+ void updateFunction(TxnId txnId, Function function) throws AlgebricksException, RemoteException;
+
+ /**
+ * update an existing datatype in the metadata, acquiring local locks on behalf
+ * of the given transaction id.
+ *
+ * @param txnId
+ * A globally unique id for an active metadata transaction.
+ * @param datatype
+ * updated Datatype instance.
+ */
+ void updateDatatype(TxnId txnId, Datatype datatype) throws AlgebricksException, RemoteException;
+
+ /**
* Adds an extension entity under the ongoing transaction job id
*
* @param txnId
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/FunctionDataSource.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/FunctionDataSource.java
index 93927dd..1303b21 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/FunctionDataSource.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/FunctionDataSource.java
@@ -52,11 +52,19 @@
public abstract class FunctionDataSource extends DataSource {
- public FunctionDataSource(DataSourceId id, INodeDomain domain) throws AlgebricksException {
+ protected final FunctionIdentifier functionId;
+
+ public FunctionDataSource(DataSourceId id, FunctionIdentifier functionId, INodeDomain domain)
+ throws AlgebricksException {
super(id, RecordUtil.FULLY_OPEN_RECORD_TYPE, null, DataSource.Type.FUNCTION, domain);
+ this.functionId = functionId;
schemaTypes = new IAType[] { itemType };
}
+ public FunctionIdentifier getFunctionId() {
+ return functionId;
+ }
+
@Override
public boolean isScanAccessPathALeaf() {
return true;
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
index 8a16014..4c19b61 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
@@ -446,7 +446,7 @@
@Override
public IFunctionInfo lookupFunction(FunctionIdentifier fid) {
- return BuiltinFunctions.lookupFunction(fid);
+ return BuiltinFunctions.getBuiltinFunctionInfo(fid);
}
public Function lookupUserDefinedFunction(FunctionSignature signature) throws AlgebricksException {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Dataset.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Dataset.java
index cc4bb09..e66057a 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Dataset.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Dataset.java
@@ -62,6 +62,7 @@
import org.apache.asterix.metadata.utils.InvertedIndexResourceFactoryProvider;
import org.apache.asterix.metadata.utils.MetadataUtil;
import org.apache.asterix.metadata.utils.RTreeResourceFactoryProvider;
+import org.apache.asterix.metadata.utils.TypeUtil;
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.IAType;
@@ -424,6 +425,14 @@
// #. finally, delete the dataset.
MetadataManager.INSTANCE.dropDataset(mdTxnCtx.getValue(), dataverseName, datasetName);
+ // drop inline types
+ if (TypeUtil.isDatasetInlineTypeName(this, recordTypeDataverseName, recordTypeName)) {
+ MetadataManager.INSTANCE.dropDatatype(mdTxnCtx.getValue(), recordTypeDataverseName, recordTypeName);
+ }
+ if (hasMetaPart() && TypeUtil.isDatasetInlineTypeName(this, metaTypeDataverseName, metaTypeName)) {
+ MetadataManager.INSTANCE.dropDatatype(mdTxnCtx.getValue(), metaTypeDataverseName, metaTypeName);
+ }
+
// Drops the associated nodegroup if it is no longer used by any other dataset.
if (dropCorrespondingNodeGroup) {
metadataProvider.getApplicationContext().getMetadataLockManager()
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 2b0fde7..968cf14 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
@@ -91,18 +91,25 @@
return paramNames;
}
+ /**
+ * @return {@code null} for non-external functions;
+ * for external function the list may contain {@code null} which means 'any' type
+ */
public List<TypeSignature> getParameterTypes() {
return paramTypes;
}
- public String getFunctionBody() {
- return body;
- }
-
+ /**
+ * @return {@code null} for non-external functions
+ */
public TypeSignature getReturnType() {
return returnType;
}
+ public String getFunctionBody() {
+ return body;
+ }
+
public String getLanguage() {
return language;
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/AbstractTupleTranslator.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/AbstractTupleTranslator.java
index 16137ef..a35246f 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/AbstractTupleTranslator.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/AbstractTupleTranslator.java
@@ -32,6 +32,7 @@
import org.apache.asterix.om.base.AInt32;
import org.apache.asterix.om.base.AInt64;
import org.apache.asterix.om.base.AMutableString;
+import org.apache.asterix.om.base.ANull;
import org.apache.asterix.om.base.ARecord;
import org.apache.asterix.om.base.AString;
import org.apache.asterix.om.types.ARecordType;
@@ -51,6 +52,9 @@
public abstract class AbstractTupleTranslator<T> implements IMetadataEntityTupleTranslator<T> {
@SuppressWarnings("unchecked")
+ protected final ISerializerDeserializer<ANull> nullSerde =
+ SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
+ @SuppressWarnings("unchecked")
protected final ISerializerDeserializer<AString> stringSerde =
SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING);
@SuppressWarnings("unchecked")
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 9c8d678..dddd28e 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
@@ -57,12 +57,13 @@
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.metadata.utils.TypeUtil;
import org.apache.asterix.om.base.ABoolean;
+import org.apache.asterix.om.base.ANull;
import org.apache.asterix.om.base.AOrderedList;
import org.apache.asterix.om.base.ARecord;
import org.apache.asterix.om.base.AString;
import org.apache.asterix.om.base.IACursor;
+import org.apache.asterix.om.base.IAObject;
import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
import org.apache.asterix.om.types.AOrderedListType;
import org.apache.asterix.om.types.ARecordType;
@@ -120,12 +121,17 @@
paramNames.add(((AString) paramNameCursor.get()).getStringValue());
}
- List<TypeSignature> paramTypes = getParamTypes(functionRecord, arity, dataverseName);
+ List<TypeSignature> paramTypes = getParamTypes(functionRecord, dataverseName);
+ TypeSignature returnType;
String returnTypeName = ((AString) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX)).getStringValue();
- String returnTypeDataverseNameCanonical = getString(functionRecord, FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME);
- TypeSignature returnType = getTypeSignature(returnTypeName, returnTypeDataverseNameCanonical, dataverseName);
+ if (returnTypeName.isEmpty()) {
+ returnType = null; // == any
+ } else {
+ String returnTypeDataverseNameCanonical = getString(functionRecord, FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME);
+ returnType = getTypeSignature(returnTypeName, returnTypeDataverseNameCanonical, dataverseName);
+ }
String definition = ((AString) functionRecord
.getValueByPos(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEFINITION_FIELD_INDEX)).getStringValue();
@@ -191,32 +197,42 @@
dependencies);
}
- private List<TypeSignature> getParamTypes(ARecord functionRecord, int arity, DataverseName functionDataverseName) {
- List<TypeSignature> paramTypes = new ArrayList<>(arity);
+ private List<TypeSignature> getParamTypes(ARecord functionRecord, DataverseName functionDataverseName) {
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);
- String paramTypeDataverseNameCanonical = getString(paramTypeRecord, FIELD_NAME_DATAVERSE_NAME);
- TypeSignature paramType =
- getTypeSignature(paramTypeName, paramTypeDataverseNameCanonical, functionDataverseName);
- paramTypes.add(paramType);
+ if (paramTypesFieldIdx < 0) {
+ return null;
+ }
+
+ AOrderedList paramTypeList = (AOrderedList) functionRecord.getValueByPos(paramTypesFieldIdx);
+ List<TypeSignature> paramTypes = new ArrayList<>(paramTypeList.size());
+ IACursor cursor = paramTypeList.getCursor();
+ while (cursor.next()) {
+ IAObject paramTypeObject = cursor.get();
+ TypeSignature paramType;
+ switch (paramTypeObject.getType().getTypeTag()) {
+ case NULL:
+ paramType = null; // == any
+ break;
+ case OBJECT:
+ ARecord paramTypeRecord = (ARecord) paramTypeObject;
+ String paramTypeName = getString(paramTypeRecord, FIELD_NAME_TYPE);
+ String paramTypeDataverseNameCanonical = getString(paramTypeRecord, FIELD_NAME_DATAVERSE_NAME);
+ paramType = getTypeSignature(paramTypeName, paramTypeDataverseNameCanonical, functionDataverseName);
+ break;
+ default:
+ throw new IllegalStateException(); //TODO:FIXME
}
- } else {
- for (int i = 0; i < arity; i++) {
- paramTypes.add(TypeUtil.ANY_TYPE_SIGNATURE);
- }
+ paramTypes.add(paramType);
}
return paramTypes;
}
private TypeSignature getTypeSignature(String typeName, String typeDataverseNameCanonical,
DataverseName functionDataverseName) {
+ // back-compat: handle "any"
if (BuiltinType.ANY.getTypeName().equals(typeName)) {
- return TypeUtil.ANY_TYPE_SIGNATURE;
+ return null; // == any
}
BuiltinType builtinType = BuiltinTypeMap.getBuiltinType(typeName);
if (builtinType != null) {
@@ -335,8 +351,9 @@
// write field 4
// Note: return type's dataverse name is written later in the open part
+ TypeSignature returnType = function.getReturnType();
fieldValue.reset();
- aString.setValue(function.getReturnType().getName());
+ aString.setValue(returnType != null ? returnType.getName() : "");
stringSerde.serialize(aString, fieldValue.getDataOutput());
recordBuilder.addField(MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_RETURN_TYPE_FIELD_INDEX, fieldValue);
@@ -429,13 +446,21 @@
}
protected void writeParameterTypes(Function function) throws HyracksDataException {
+ List<TypeSignature> parameterTypes = function.getParameterTypes();
+ if (parameterTypes == null) {
+ return;
+ }
OrderedListBuilder listBuilder = new OrderedListBuilder();
ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
listBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
- for (TypeSignature paramType : function.getParameterTypes()) {
+ for (TypeSignature paramType : parameterTypes) {
itemValue.reset();
- writeTypeRecord(paramType.getDataverseName(), paramType.getName(), function.getDataverseName(),
- itemValue.getDataOutput());
+ if (paramType == null) {
+ nullSerde.serialize(ANull.NULL, itemValue.getDataOutput());
+ } else {
+ writeTypeRecord(paramType.getDataverseName(), paramType.getName(), function.getDataverseName(),
+ itemValue.getDataOutput());
+ }
listBuilder.addItem(itemValue);
}
fieldValue.reset();
@@ -487,18 +512,21 @@
}
protected void writeReturnTypeDataverseName(Function function) throws HyracksDataException {
- DataverseName returnTypeDataverseName = function.getReturnType().getDataverseName();
- boolean skipReturnTypeDataverseName =
- returnTypeDataverseName == null || returnTypeDataverseName.equals(function.getDataverseName());
- if (!skipReturnTypeDataverseName) {
- fieldName.reset();
- aString.setValue(FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME);
- stringSerde.serialize(aString, fieldName.getDataOutput());
- fieldValue.reset();
- aString.setValue(returnTypeDataverseName.getCanonicalForm());
- stringSerde.serialize(aString, fieldValue.getDataOutput());
- recordBuilder.addField(fieldName, fieldValue);
+ TypeSignature returnType = function.getReturnType();
+ if (returnType == null) {
+ return;
}
+ DataverseName returnTypeDataverseName = returnType.getDataverseName();
+ if (returnTypeDataverseName == null || returnTypeDataverseName.equals(function.getDataverseName())) {
+ return;
+ }
+ fieldName.reset();
+ aString.setValue(FIELD_NAME_RETURN_TYPE_DATAVERSE_NAME);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+ fieldValue.reset();
+ aString.setValue(returnTypeDataverseName.getCanonicalForm());
+ stringSerde.serialize(aString, fieldValue.getDataOutput());
+ recordBuilder.addField(fieldName, fieldValue);
}
protected void writeNullCall(Function function) throws HyracksDataException {
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 f37823c..029b13a 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
@@ -19,6 +19,7 @@
package org.apache.asterix.metadata.functions;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.asterix.common.exceptions.AsterixException;
@@ -62,25 +63,24 @@
private static IFunctionInfo getScalarFunctionInfo(MetadataProvider metadataProvider, Function function)
throws AlgebricksException {
- if (function.getDeterministic() == null) {
- throw new AsterixException(ErrorCode.METADATA_ERROR, "");
- }
- List<IAType> paramTypes = new ArrayList<>(function.getParameterTypes().size());
- for (TypeSignature ts : function.getParameterTypes()) {
- IAType paramType = resolveFunctionType(ts, metadataProvider);
- paramTypes.add(paramType);
- }
+ List<IAType> paramTypes = getParameterTypes(function, metadataProvider);
- IAType returnType = resolveFunctionType(function.getReturnType(), metadataProvider);
+ IAType returnType = getType(function.getReturnType(), metadataProvider);
IResultTypeComputer typeComputer = new ExternalTypeComputer(returnType, paramTypes);
ExternalFunctionLanguage lang = getExternalFunctionLanguage(function.getLanguage());
+ Boolean deterministic = function.getDeterministic();
+ if (deterministic == null) {
+ // all external functions should store 'deterministic' property
+ throw new AsterixException(ErrorCode.METADATA_ERROR, function.getSignature().toString());
+ }
+
return new ExternalScalarFunctionInfo(function.getSignature().createFunctionIdentifier(), paramTypes,
returnType, typeComputer, lang, function.getLibraryDataverseName(), function.getLibraryName(),
- function.getExternalIdentifier(), function.getResources(), function.getDeterministic());
+ function.getExternalIdentifier(), function.getResources(), deterministic);
}
private static IFunctionInfo getUnnestFunctionInfo(MetadataProvider metadataProvider, Function function) {
@@ -95,9 +95,41 @@
return null;
}
- private static IAType resolveFunctionType(TypeSignature typeSignature, MetadataProvider metadataProvider)
+ private static List<IAType> getParameterTypes(Function function, MetadataProvider metadataProvider)
throws AlgebricksException {
+ int arity = function.getArity();
+ if (arity == 0) {
+ return Collections.emptyList();
+ } else if (arity >= 0) {
+ List<IAType> types = new ArrayList<>(arity);
+ List<TypeSignature> typeSignatures = function.getParameterTypes();
+ if (typeSignatures != null) {
+ if (typeSignatures.size() != arity) {
+ throw new AsterixException(ErrorCode.METADATA_ERROR, function.getSignature().toString());
+ }
+ for (TypeSignature ts : typeSignatures) {
+ IAType paramType = getType(ts, metadataProvider);
+ types.add(paramType);
+ }
+ } else {
+ for (int i = 0; i < arity; i++) {
+ types.add(BuiltinType.ANY);
+ }
+ }
+ return types;
+ } else {
+ // we don't yet support variadic external functions
+ throw new AsterixException(ErrorCode.METADATA_ERROR, function.getSignature().toString());
+ }
+ }
+
+ private static IAType getType(TypeSignature typeSignature, MetadataProvider metadataProvider)
+ throws AlgebricksException {
+ if (typeSignature == null) {
+ return BuiltinType.ANY;
+ }
String typeName = typeSignature.getName();
+ // back-compat: handle "any"
if (BuiltinType.ANY.getTypeName().equals(typeName)) {
return BuiltinType.ANY;
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java
index 11dc1ee..7660909 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/TypeUtil.java
@@ -19,6 +19,8 @@
package org.apache.asterix.metadata.utils;
import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.List;
@@ -28,12 +30,12 @@
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.metadata.entities.Dataset;
+import org.apache.asterix.metadata.entities.Function;
import org.apache.asterix.metadata.entities.Index;
import org.apache.asterix.om.typecomputer.impl.TypeComputeUtils;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.ATypeTag;
import org.apache.asterix.om.types.AUnionType;
-import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.types.TypeSignature;
import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
@@ -46,8 +48,6 @@
*/
public class TypeUtil {
- public static final TypeSignature ANY_TYPE_SIGNATURE = new TypeSignature(BuiltinType.ANY);
-
private static final char TYPE_NAME_DELIMITER = '$';
private static final String DATASET_INLINE_TYPE_PREFIX = "$d$t$";
@@ -263,7 +263,12 @@
}
public static boolean isDatasetInlineTypeName(Dataset dataset, DataverseName typeDataverseName, String typeName) {
- return dataset.getDataverseName().equals(typeDataverseName) && typeName.startsWith(DATASET_INLINE_TYPE_PREFIX);
+ return isInlineTypeName(dataset.getDataverseName(), typeDataverseName, typeName, DATASET_INLINE_TYPE_PREFIX);
+ }
+
+ private static boolean isInlineTypeName(DataverseName entityDataverseName, DataverseName typeDataverseName,
+ String typeName, String inlineTypePrefix) {
+ return entityDataverseName.equals(typeDataverseName) && typeName.startsWith(inlineTypePrefix);
}
public static String createFunctionParameterTypeName(String functionName, int arity, int parameterIndex) {
@@ -277,4 +282,39 @@
return sb.toString();
}
+
+ public static boolean isFunctionInlineTypeName(Function function, DataverseName typeDataverseName,
+ String typeName) {
+ return isInlineTypeName(function.getDataverseName(), typeDataverseName, typeName, FUNCTION_INLINE_TYPE_PREFIX);
+ }
+
+ public static String getFullyQualifiedDisplayName(DataverseName dataverseName, String typeName) {
+ return dataverseName + "." + typeName;
+ }
+
+ /**
+ * Inline type names are unique within a function, so we don't need to perform duplicate elimination
+ */
+ public static List<TypeSignature> getFunctionInlineTypes(Function function) {
+ List<TypeSignature> inlineTypes = Collections.emptyList();
+ TypeSignature returnType = function.getReturnType();
+ if (returnType != null
+ && isFunctionInlineTypeName(function, returnType.getDataverseName(), returnType.getName())) {
+ inlineTypes = new ArrayList<>();
+ inlineTypes.add(returnType);
+ }
+ List<TypeSignature> parameterTypes = function.getParameterTypes();
+ if (parameterTypes != null) {
+ for (TypeSignature parameterType : parameterTypes) {
+ if (parameterType != null && isFunctionInlineTypeName(function, parameterType.getDataverseName(),
+ parameterType.getName())) {
+ if (inlineTypes.isEmpty()) {
+ inlineTypes = new ArrayList<>();
+ }
+ inlineTypes.add(parameterType);
+ }
+ }
+ }
+ return inlineTypes;
+ }
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ExpressionTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ExpressionTypeComputer.java
index 1dcf6a6..e581140 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ExpressionTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ExpressionTypeComputer.java
@@ -20,10 +20,8 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
-import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.om.constants.AsterixConstantValue;
-import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.asterix.om.functions.ExternalFunctionInfo;
+import org.apache.asterix.om.functions.FunctionInfo;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
@@ -35,7 +33,6 @@
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
public class ExpressionTypeComputer implements IExpressionTypeComputer {
@@ -69,18 +66,7 @@
private IAType getTypeForFunction(AbstractFunctionCallExpression expr, IVariableTypeEnvironment env,
IMetadataProvider<?, ?> mp) throws AlgebricksException {
- FunctionIdentifier fi = expr.getFunctionIdentifier();
- // Note: built-in functions + udfs
- IResultTypeComputer rtc;
- FunctionSignature signature = new FunctionSignature(fi);
- if (BuiltinFunctions.isBuiltinCompilerFunction(signature, true)) {
- rtc = BuiltinFunctions.getResultTypeComputer(fi);
- } else {
- rtc = ((ExternalFunctionInfo) expr.getFunctionInfo()).getResultTypeComputer();
- }
- if (rtc == null) {
- throw new AlgebricksException("Type computer missing for " + fi);
- }
+ IResultTypeComputer rtc = ((FunctionInfo) expr.getFunctionInfo()).getResultTypeComputer();
return rtc.computeType(expr, env, mp);
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/PartialAggregationTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/PartialAggregationTypeComputer.java
index 4a0384d..f012f5c 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/PartialAggregationTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/PartialAggregationTypeComputer.java
@@ -19,6 +19,7 @@
package org.apache.asterix.dataflow.data.common;
import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.FunctionInfo;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
@@ -45,7 +46,6 @@
private Object getTypeForFunction(AbstractFunctionCallExpression expr, IVariableTypeEnvironment env,
IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
- return BuiltinFunctions.getResultTypeComputer(expr.getFunctionIdentifier()).computeType(expr, env,
- metadataProvider);
+ return ((FunctionInfo) expr.getFunctionInfo()).getResultTypeComputer().computeType(expr, env, metadataProvider);
}
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctionInfo.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctionInfo.java
new file mode 100644
index 0000000..acb348d
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctionInfo.java
@@ -0,0 +1,39 @@
+/*
+ * 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.om.functions;
+
+import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+public final class BuiltinFunctionInfo extends FunctionInfo {
+ private static final long serialVersionUID = -6013109889177637590L;
+
+ private final boolean isPrivate;
+
+ public BuiltinFunctionInfo(FunctionIdentifier fi, IResultTypeComputer typeComputer, boolean isFunctional,
+ boolean isPrivate) {
+ super(fi, typeComputer, isFunctional);
+ this.isPrivate = isPrivate;
+ }
+
+ public boolean isPrivate() {
+ return isPrivate;
+ }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
index 96ad4a9..f74e730 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
@@ -34,7 +34,6 @@
import java.util.Set;
import org.apache.asterix.common.functions.FunctionConstants;
-import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.asterix.om.typecomputer.impl.ABinaryTypeComputer;
import org.apache.asterix.om.typecomputer.impl.ABooleanArrayContainsTypeComputer;
@@ -136,7 +135,6 @@
import org.apache.asterix.om.typecomputer.impl.UnaryBinaryInt64TypeComputer;
import org.apache.asterix.om.typecomputer.impl.UniformInputTypeComputer;
import org.apache.asterix.om.typecomputer.impl.UnorderedListConstructorTypeComputer;
-import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
@@ -149,34 +147,27 @@
public class BuiltinFunctions {
- public enum SpatialFilterKind {
- SI
- }
-
- private static final FunctionInfoRepository registeredFunctions = new FunctionInfoRepository();
- private static final Map<IFunctionInfo, ATypeHierarchy.Domain> registeredFunctionsDomain = new HashMap<>();
-
- // it is supposed to be an identity mapping
- private static final Map<IFunctionInfo, IFunctionInfo> builtinPublicFunctionsSet = new HashMap<>();
- private static final Map<IFunctionInfo, IFunctionInfo> builtinPrivateFunctionsSet = new HashMap<>();
- private static final Map<IFunctionInfo, IResultTypeComputer> funTypeComputer = new HashMap<>();
- private static final Map<IFunctionInfo, Set<? extends BuiltinFunctionProperty>> builtinFunctionProperties =
+ private static final Map<FunctionIdentifier, BuiltinFunctionInfo> registeredFunctions = new HashMap<>();
+ private static final Map<FunctionIdentifier, Set<? extends BuiltinFunctionProperty>> builtinFunctionProperties =
new HashMap<>();
- private static final Set<IFunctionInfo> builtinAggregateFunctions = new HashSet<>();
- private static final Map<IFunctionInfo, IFunctionToDataSourceRewriter> datasourceFunctions = new HashMap<>();
- private static final Set<IFunctionInfo> similarityFunctions = new HashSet<>();
- private static final Set<IFunctionInfo> globalAggregateFunctions = new HashSet<>();
- private static final Map<IFunctionInfo, IFunctionInfo> aggregateToLocalAggregate = new HashMap<>();
- private static final Map<IFunctionInfo, IFunctionInfo> aggregateToIntermediateAggregate = new HashMap<>();
- private static final Map<IFunctionInfo, IFunctionInfo> aggregateToGlobalAggregate = new HashMap<>();
- private static final Map<IFunctionInfo, IFunctionInfo> aggregateToSerializableAggregate = new HashMap<>();
- private static final Map<IFunctionInfo, Boolean> builtinUnnestingFunctions = new HashMap<>();
- private static final Map<IFunctionInfo, IFunctionInfo> scalarToAggregateFunctionMap = new HashMap<>();
- private static final Map<IFunctionInfo, IFunctionInfo> distinctToRegularAggregateFunctionMap = new HashMap<>();
- private static final Map<IFunctionInfo, IFunctionInfo> sqlToWindowFunctions = new HashMap<>();
- private static final Set<IFunctionInfo> windowFunctions = new HashSet<>();
- private static final Map<IFunctionInfo, SpatialFilterKind> spatialFilterFunctions = new HashMap<>();
+ private static final Map<FunctionIdentifier, IFunctionToDataSourceRewriter> datasourceFunctions = new HashMap<>();
+ private static final Map<FunctionIdentifier, Boolean> builtinUnnestingFunctions = new HashMap<>();
+
+ private static final Set<FunctionIdentifier> builtinAggregateFunctions = new HashSet<>();
+ private static final Set<FunctionIdentifier> globalAggregateFunctions = new HashSet<>();
+ private static final Map<FunctionIdentifier, FunctionIdentifier> aggregateToLocalAggregate = new HashMap<>();
+ private static final Map<FunctionIdentifier, FunctionIdentifier> aggregateToIntermediateAggregate = new HashMap<>();
+ private static final Map<FunctionIdentifier, FunctionIdentifier> aggregateToGlobalAggregate = new HashMap<>();
+ private static final Map<FunctionIdentifier, FunctionIdentifier> aggregateToSerializableAggregate = new HashMap<>();
+ private static final Map<FunctionIdentifier, FunctionIdentifier> scalarToAggregateFunctionMap = new HashMap<>();
+ private static final Map<FunctionIdentifier, FunctionIdentifier> distinctToRegularAggregateFunctionMap =
+ new HashMap<>();
+ private static final Map<FunctionIdentifier, FunctionIdentifier> sqlToWindowFunctions = new HashMap<>();
+ private static final Set<FunctionIdentifier> windowFunctions = new HashSet<>();
+
+ private static final Map<FunctionIdentifier, SpatialFilterKind> spatialFilterFunctions = new HashMap<>();
+ private static final Set<FunctionIdentifier> similarityFunctions = new HashSet<>();
public static final FunctionIdentifier TYPE_OF = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "type-of", 1);
public static final FunctionIdentifier GET_HANDLE =
@@ -1602,16 +1593,7 @@
public static final FunctionIdentifier DECODE_DATAVERSE_NAME =
new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "decode-dataverse-name", 1);
- public static IFunctionInfo getAsterixFunctionInfo(FunctionIdentifier fid) {
- return registeredFunctions.get(fid);
- }
-
- public static FunctionInfo lookupFunction(FunctionIdentifier fid) {
- return (FunctionInfo) registeredFunctions.get(fid);
- }
-
static {
-
// first, take care of Algebricks builtin functions
addFunction(IS_MISSING, BooleanOnlyTypeComputer.INSTANCE, true);
addFunction(IS_UNKNOWN, BooleanOnlyTypeComputer.INSTANCE, true);
@@ -1692,9 +1674,9 @@
addFunction(FLOAT_CONSTRUCTOR, AFloatTypeComputer.INSTANCE, true);
addPrivateFunction(FUZZY_EQ, BooleanFunctionTypeComputer.INSTANCE, true);
- addPrivateFunction(GET_HANDLE, null, true);
+ addPrivateFunction(GET_HANDLE, AnyTypeComputer.INSTANCE, true);
addPrivateFunction(GET_ITEM, NonTaggedGetItemResultType.INSTANCE, true);
- addPrivateFunction(GET_DATA, null, true);
+ addPrivateFunction(GET_DATA, AnyTypeComputer.INSTANCE, true);
addPrivateFunction(GRAM_TOKENS, OrderedListOfAStringTypeComputer.INSTANCE, true);
addPrivateFunction(HASHED_GRAM_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE, true);
addPrivateFunction(HASHED_WORD_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE, true);
@@ -1705,8 +1687,8 @@
addFunction(INT64_CONSTRUCTOR, AInt64TypeComputer.INSTANCE, true);
addFunction(LEN, AInt64TypeComputer.INSTANCE, true);
addFunction(LINE_CONSTRUCTOR, ALineTypeComputer.INSTANCE, true);
- addPrivateFunction(MAKE_FIELD_INDEX_HANDLE, null, true);
- addPrivateFunction(MAKE_FIELD_NAME_HANDLE, null, true);
+ addPrivateFunction(MAKE_FIELD_INDEX_HANDLE, AnyTypeComputer.INSTANCE, true);
+ addPrivateFunction(MAKE_FIELD_NAME_HANDLE, AnyTypeComputer.INSTANCE, true);
addPrivateFunction(NUMERIC_UNARY_MINUS, NumericUnaryTypeComputer.INSTANCE, true);
addPrivateFunction(NUMERIC_SUBTRACT, NumericAddSubMulDivTypeComputer.INSTANCE_SUB, true);
@@ -2146,7 +2128,7 @@
addFunction(SPATIAL_AREA, ADoubleTypeComputer.INSTANCE, true);
addFunction(SPATIAL_CELL, ARectangleTypeComputer.INSTANCE, true);
addFunction(SPATIAL_DISTANCE, ADoubleTypeComputer.INSTANCE, true);
- addFunctionWithDomain(SPATIAL_INTERSECT, ATypeHierarchy.Domain.SPATIAL, ABooleanTypeComputer.INSTANCE, true);
+ addFunction(SPATIAL_INTERSECT, ABooleanTypeComputer.INSTANCE, true);
addFunction(GET_POINT_X_COORDINATE_ACCESSOR, ADoubleTypeComputer.INSTANCE, true);
addFunction(GET_POINT_Y_COORDINATE_ACCESSOR, ADoubleTypeComputer.INSTANCE, true);
addFunction(GET_CIRCLE_RADIUS_ACCESSOR, ADoubleTypeComputer.INSTANCE, true);
@@ -2235,7 +2217,7 @@
addFunction(TID, AInt64TypeComputer.INSTANCE, true);
addFunction(TIME_CONSTRUCTOR, ATimeTypeComputer.INSTANCE, true);
- addPrivateFunction(TYPE_OF, null, true);
+ addPrivateFunction(TYPE_OF, AnyTypeComputer.INSTANCE, true);
addPrivateFunction(UNORDERED_LIST_CONSTRUCTOR, UnorderedListConstructorTypeComputer.INSTANCE, true);
addFunction(WORD_TOKENS, OrderedListOfAStringTypeComputer.INSTANCE, true);
@@ -3084,77 +3066,65 @@
public static void addDatasourceFunction(FunctionIdentifier fi, IFunctionToDataSourceRewriter transformer,
DataSourceFunctionProperty... properties) {
- IFunctionInfo finfo = getAsterixFunctionInfo(fi);
- datasourceFunctions.put(finfo, transformer);
- registerFunctionProperties(finfo, DataSourceFunctionProperty.class, properties);
+ datasourceFunctions.put(fi, transformer);
+ registerFunctionProperties(fi, DataSourceFunctionProperty.class, properties);
}
public static IFunctionToDataSourceRewriter getDatasourceTransformer(FunctionIdentifier fi) {
- return datasourceFunctions.getOrDefault(getAsterixFunctionInfo(fi), IFunctionToDataSourceRewriter.NOOP);
+ return datasourceFunctions.get(fi);
}
- public static boolean isBuiltinCompilerFunction(FunctionSignature signature, boolean includePrivateFunctions) {
- return getBuiltinCompilerFunction(signature.getName(), signature.getArity(), includePrivateFunctions) != null;
+ public static BuiltinFunctionInfo getBuiltinFunctionInfo(FunctionIdentifier fi) {
+ return registeredFunctions.get(fi);
}
- public static FunctionIdentifier getBuiltinCompilerFunction(String name, int arity,
- boolean includePrivateFunctions) {
- FunctionIdentifier fi = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, name, arity);
- IFunctionInfo finfo = getAsterixFunctionInfo(fi);
- if (builtinPublicFunctionsSet.containsKey(finfo)
- || (includePrivateFunctions && builtinPrivateFunctionsSet.containsKey(finfo))) {
- return fi;
+ public static BuiltinFunctionInfo resolveBuiltinFunction(String name, int arity) {
+ //TODO:optimize
+ BuiltinFunctionInfo finfo;
+ finfo = getBuiltinFunctionInfo(new FunctionIdentifier(FunctionConstants.ASTERIX_NS, name, arity));
+ if (finfo != null) {
+ return finfo;
}
- fi = new FunctionIdentifier(AlgebricksBuiltinFunctions.ALGEBRICKS_NS, name, arity);
- finfo = getAsterixFunctionInfo(fi);
- return builtinPublicFunctionsSet.containsKey(finfo)
- || (includePrivateFunctions && builtinPrivateFunctionsSet.containsKey(finfo)) ? fi : null;
+ finfo = getBuiltinFunctionInfo(
+ new FunctionIdentifier(FunctionConstants.ASTERIX_NS, name, FunctionIdentifier.VARARGS));
+ if (finfo != null) {
+ return finfo;
+ }
+ finfo = getBuiltinFunctionInfo(new FunctionIdentifier(AlgebricksBuiltinFunctions.ALGEBRICKS_NS, name, arity));
+ if (finfo != null) {
+ return finfo;
+ }
+ return getBuiltinFunctionInfo(
+ new FunctionIdentifier(AlgebricksBuiltinFunctions.ALGEBRICKS_NS, name, FunctionIdentifier.VARARGS));
}
public static boolean isBuiltinAggregateFunction(FunctionIdentifier fi) {
- return builtinAggregateFunctions.contains(getAsterixFunctionInfo(fi));
+ return builtinAggregateFunctions.contains(fi);
}
public static boolean isBuiltinUnnestingFunction(FunctionIdentifier fi) {
- return builtinUnnestingFunctions.get(getAsterixFunctionInfo(fi)) != null;
+ return builtinUnnestingFunctions.containsKey(fi);
}
public static boolean returnsUniqueValues(FunctionIdentifier fi) {
- Boolean ruv = builtinUnnestingFunctions.get(getAsterixFunctionInfo(fi));
- return ruv != null && ruv.booleanValue();
- }
-
- public static FunctionIdentifier getLocalAggregateFunction(FunctionIdentifier fi) {
- return aggregateToLocalAggregate.get(getAsterixFunctionInfo(fi)).getFunctionIdentifier();
- }
-
- public static FunctionIdentifier getGlobalAggregateFunction(FunctionIdentifier fi) {
- return aggregateToGlobalAggregate.get(getAsterixFunctionInfo(fi)).getFunctionIdentifier();
+ Boolean ruv = builtinUnnestingFunctions.get(fi);
+ return ruv != null && ruv;
}
public static FunctionIdentifier getIntermediateAggregateFunction(FunctionIdentifier fi) {
- IFunctionInfo funcInfo = aggregateToIntermediateAggregate.get(getAsterixFunctionInfo(fi));
- if (funcInfo == null) {
- return null;
- }
- return funcInfo.getFunctionIdentifier();
- }
-
- public static FunctionIdentifier getBuiltinFunctionIdentifier(FunctionIdentifier fi) {
- IFunctionInfo finfo = getAsterixFunctionInfo(fi);
- return finfo == null ? null : finfo.getFunctionIdentifier();
+ return aggregateToIntermediateAggregate.get(fi);
}
public static AggregateFunctionCallExpression makeAggregateFunctionExpression(FunctionIdentifier fi,
List<Mutable<ILogicalExpression>> args) {
- IFunctionInfo finfo = getAsterixFunctionInfo(fi);
- IFunctionInfo fiLocal = aggregateToLocalAggregate.get(finfo);
- IFunctionInfo fiGlobal = aggregateToGlobalAggregate.get(finfo);
+ IFunctionInfo finfo = getBuiltinFunctionInfo(fi);
+ FunctionIdentifier fiLocal = aggregateToLocalAggregate.get(fi);
+ FunctionIdentifier fiGlobal = aggregateToGlobalAggregate.get(fi);
if (fiLocal != null && fiGlobal != null) {
AggregateFunctionCallExpression fun = new AggregateFunctionCallExpression(finfo, true, args);
- fun.setStepTwoAggregate(fiGlobal);
- fun.setStepOneAggregate(fiLocal);
+ fun.setStepTwoAggregate(getBuiltinFunctionInfo(fiGlobal));
+ fun.setStepOneAggregate(getBuiltinFunctionInfo(fiLocal));
return fun;
} else {
return new AggregateFunctionCallExpression(finfo, false, args);
@@ -3162,166 +3132,151 @@
}
public static boolean isAggregateFunctionSerializable(FunctionIdentifier fi) {
- IFunctionInfo finfo = getAsterixFunctionInfo(fi);
- return aggregateToSerializableAggregate.get(finfo) != null;
+ return aggregateToSerializableAggregate.containsKey(fi);
}
public static AggregateFunctionCallExpression makeSerializableAggregateFunctionExpression(FunctionIdentifier fi,
List<Mutable<ILogicalExpression>> args) {
- IFunctionInfo finfo = getAsterixFunctionInfo(fi);
- IFunctionInfo serializableFinfo = aggregateToSerializableAggregate.get(finfo);
- if (serializableFinfo == null) {
- throw new IllegalStateException(
- "no serializable implementation for aggregate function " + serializableFinfo);
+ FunctionIdentifier serializableFi = aggregateToSerializableAggregate.get(fi);
+ if (serializableFi == null) {
+ throw new IllegalStateException("no serializable implementation for aggregate function " + fi);
}
+ IFunctionInfo serializableFinfo = getBuiltinFunctionInfo(serializableFi);
- IFunctionInfo fiLocal = aggregateToLocalAggregate.get(serializableFinfo);
- IFunctionInfo fiGlobal = aggregateToGlobalAggregate.get(serializableFinfo);
+ FunctionIdentifier fiLocal = aggregateToLocalAggregate.get(serializableFi);
+ FunctionIdentifier fiGlobal = aggregateToGlobalAggregate.get(serializableFi);
if (fiLocal != null && fiGlobal != null) {
AggregateFunctionCallExpression fun = new AggregateFunctionCallExpression(serializableFinfo, true, args);
- fun.setStepTwoAggregate(fiGlobal);
- fun.setStepOneAggregate(fiLocal);
+ fun.setStepTwoAggregate(getBuiltinFunctionInfo(fiGlobal));
+ fun.setStepOneAggregate(getBuiltinFunctionInfo(fiLocal));
return fun;
} else {
return new AggregateFunctionCallExpression(serializableFinfo, false, args);
}
}
- public static IResultTypeComputer getResultTypeComputer(FunctionIdentifier fi) {
- return funTypeComputer.get(getAsterixFunctionInfo(fi));
- }
-
public static FunctionIdentifier getAggregateFunction(FunctionIdentifier scalarVersionOfAggregate) {
- IFunctionInfo finfo = scalarToAggregateFunctionMap.get(getAsterixFunctionInfo(scalarVersionOfAggregate));
- return finfo == null ? null : finfo.getFunctionIdentifier();
+ return scalarToAggregateFunctionMap.get(scalarVersionOfAggregate);
}
public static FunctionIdentifier getAggregateFunctionForDistinct(FunctionIdentifier distinctVersionOfAggregate) {
- IFunctionInfo finfo =
- distinctToRegularAggregateFunctionMap.get(getAsterixFunctionInfo(distinctVersionOfAggregate));
- return finfo == null ? null : finfo.getFunctionIdentifier();
+ return distinctToRegularAggregateFunctionMap.get(distinctVersionOfAggregate);
}
public static void addFunction(FunctionIdentifier fi, IResultTypeComputer typeComputer, boolean isFunctional) {
- addFunctionWithDomain(fi, ATypeHierarchy.Domain.ANY, typeComputer, isFunctional);
- }
-
- public static void addFunctionWithDomain(FunctionIdentifier fi, ATypeHierarchy.Domain funcDomain,
- IResultTypeComputer typeComputer, boolean isFunctional) {
- IFunctionInfo functionInfo = new FunctionInfo(fi, isFunctional);
- builtinPublicFunctionsSet.put(functionInfo, functionInfo);
- funTypeComputer.put(functionInfo, typeComputer);
- registeredFunctions.put(fi, functionInfo);
- registeredFunctionsDomain.put(functionInfo, funcDomain);
+ addFunction(new BuiltinFunctionInfo(fi, typeComputer, isFunctional, false));
}
public static void addPrivateFunction(FunctionIdentifier fi, IResultTypeComputer typeComputer,
boolean isFunctional) {
- IFunctionInfo functionInfo = new FunctionInfo(fi, isFunctional);
- builtinPrivateFunctionsSet.put(functionInfo, functionInfo);
- funTypeComputer.put(functionInfo, typeComputer);
- registeredFunctions.put(fi, functionInfo);
+ addFunction(new BuiltinFunctionInfo(fi, typeComputer, isFunctional, true));
}
- private static <T extends Enum<T> & BuiltinFunctionProperty> void registerFunctionProperties(IFunctionInfo finfo,
+ private static void addFunction(BuiltinFunctionInfo functionInfo) {
+ registeredFunctions.put(functionInfo.getFunctionIdentifier(), functionInfo);
+ }
+
+ private static <T extends Enum<T> & BuiltinFunctionProperty> void registerFunctionProperties(FunctionIdentifier fid,
Class<T> propertyClass, T[] properties) {
if (properties == null) {
return;
}
Set<T> propertySet = EnumSet.noneOf(propertyClass);
Collections.addAll(propertySet, properties);
- builtinFunctionProperties.put(finfo, propertySet);
+ builtinFunctionProperties.put(fid, propertySet);
}
public static boolean builtinFunctionHasProperty(FunctionIdentifier fi, BuiltinFunctionProperty property) {
- Set<? extends BuiltinFunctionProperty> propertySet = builtinFunctionProperties.get(getAsterixFunctionInfo(fi));
+ Set<? extends BuiltinFunctionProperty> propertySet = builtinFunctionProperties.get(fi);
return propertySet != null && propertySet.contains(property);
}
public static void addAgg(FunctionIdentifier fi) {
- builtinAggregateFunctions.add(getAsterixFunctionInfo(fi));
+ builtinAggregateFunctions.add(fi);
}
public static void addLocalAgg(FunctionIdentifier fi, FunctionIdentifier localfi) {
- aggregateToLocalAggregate.put(getAsterixFunctionInfo(fi), getAsterixFunctionInfo(localfi));
+ aggregateToLocalAggregate.put(fi, localfi);
}
public static void addIntermediateAgg(FunctionIdentifier fi, FunctionIdentifier globalfi) {
- aggregateToIntermediateAggregate.put(getAsterixFunctionInfo(fi), getAsterixFunctionInfo(globalfi));
+ aggregateToIntermediateAggregate.put(fi, globalfi);
}
public static void addGlobalAgg(FunctionIdentifier fi, FunctionIdentifier globalfi) {
- aggregateToGlobalAggregate.put(getAsterixFunctionInfo(fi), getAsterixFunctionInfo(globalfi));
- globalAggregateFunctions.add(getAsterixFunctionInfo(globalfi));
+ aggregateToGlobalAggregate.put(fi, globalfi);
+ globalAggregateFunctions.add(globalfi);
}
public static void addUnnestFun(FunctionIdentifier fi, boolean returnsUniqueValues) {
- builtinUnnestingFunctions.put(getAsterixFunctionInfo(fi), returnsUniqueValues);
+ builtinUnnestingFunctions.put(fi, returnsUniqueValues);
}
public static void addSerialAgg(FunctionIdentifier fi, FunctionIdentifier serialfi) {
- aggregateToSerializableAggregate.put(getAsterixFunctionInfo(fi), getAsterixFunctionInfo(serialfi));
+ aggregateToSerializableAggregate.put(fi, serialfi);
}
public static void addScalarAgg(FunctionIdentifier fi, FunctionIdentifier scalarfi) {
- scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(scalarfi), getAsterixFunctionInfo(fi));
+ scalarToAggregateFunctionMap.put(scalarfi, fi);
}
public static void addDistinctAgg(FunctionIdentifier distinctfi, FunctionIdentifier fi) {
- distinctToRegularAggregateFunctionMap.put(getAsterixFunctionInfo(distinctfi), getAsterixFunctionInfo(fi));
+ distinctToRegularAggregateFunctionMap.put(distinctfi, fi);
}
public static void addWindowFunction(FunctionIdentifier sqlfi, FunctionIdentifier winfi,
WindowFunctionProperty... properties) {
- IFunctionInfo wininfo = getAsterixFunctionInfo(winfi);
if (sqlfi != null) {
- sqlToWindowFunctions.put(getAsterixFunctionInfo(sqlfi), wininfo);
+ sqlToWindowFunctions.put(sqlfi, winfi);
}
- windowFunctions.add(wininfo);
- registerFunctionProperties(wininfo, WindowFunctionProperty.class, properties);
+ windowFunctions.add(winfi);
+ registerFunctionProperties(winfi, WindowFunctionProperty.class, properties);
}
public static FunctionIdentifier getWindowFunction(FunctionIdentifier sqlfi) {
- IFunctionInfo finfo = sqlToWindowFunctions.get(getAsterixFunctionInfo(sqlfi));
- return finfo == null ? null : finfo.getFunctionIdentifier();
+ return sqlToWindowFunctions.get(sqlfi);
}
public static boolean isWindowFunction(FunctionIdentifier winfi) {
- return windowFunctions.contains(getAsterixFunctionInfo(winfi));
+ return windowFunctions.contains(winfi);
}
public static AbstractFunctionCallExpression makeWindowFunctionExpression(FunctionIdentifier winfi,
List<Mutable<ILogicalExpression>> args) {
- IFunctionInfo finfo = getAsterixFunctionInfo(winfi);
+ IFunctionInfo finfo = getBuiltinFunctionInfo(winfi);
if (finfo == null) {
- throw new IllegalStateException("no implementation for window function " + finfo);
+ throw new IllegalStateException("no implementation for window function " + winfi);
}
return new StatefulFunctionCallExpression(finfo, UnpartitionedPropertyComputer.INSTANCE, args);
}
+ public enum SpatialFilterKind {
+ SI
+ }
+
static {
- spatialFilterFunctions.put(getAsterixFunctionInfo(BuiltinFunctions.SPATIAL_INTERSECT), SpatialFilterKind.SI);
+ spatialFilterFunctions.put(BuiltinFunctions.SPATIAL_INTERSECT, SpatialFilterKind.SI);
}
public static boolean isGlobalAggregateFunction(FunctionIdentifier fi) {
- return globalAggregateFunctions.contains(getAsterixFunctionInfo(fi));
+ return globalAggregateFunctions.contains(fi);
}
public static boolean isSpatialFilterFunction(FunctionIdentifier fi) {
- return spatialFilterFunctions.get(getAsterixFunctionInfo(fi)) != null;
+ return spatialFilterFunctions.get(fi) != null;
}
static {
- similarityFunctions.add(getAsterixFunctionInfo(SIMILARITY_JACCARD));
- similarityFunctions.add(getAsterixFunctionInfo(SIMILARITY_JACCARD_CHECK));
- similarityFunctions.add(getAsterixFunctionInfo(EDIT_DISTANCE));
- similarityFunctions.add(getAsterixFunctionInfo(EDIT_DISTANCE_CHECK));
- similarityFunctions.add(getAsterixFunctionInfo(EDIT_DISTANCE_CONTAINS));
+ similarityFunctions.add(SIMILARITY_JACCARD);
+ similarityFunctions.add(SIMILARITY_JACCARD_CHECK);
+ similarityFunctions.add(EDIT_DISTANCE);
+ similarityFunctions.add(EDIT_DISTANCE_CHECK);
+ similarityFunctions.add(EDIT_DISTANCE_CONTAINS);
}
public static boolean isSimilarityFunction(FunctionIdentifier fi) {
- return similarityFunctions.contains(getAsterixFunctionInfo(fi));
+ return similarityFunctions.contains(fi);
}
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
index 8707018..7477330 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
@@ -30,12 +30,11 @@
public class ExternalFunctionInfo extends FunctionInfo implements IExternalFunctionInfo {
- private static final long serialVersionUID = 3L;
+ private static final long serialVersionUID = 4L;
private final FunctionKind kind;
private final List<IAType> parameterTypes;
private final IAType returnType;
- private final transient IResultTypeComputer rtc;
private final ExternalFunctionLanguage language;
private final DataverseName libraryDataverseName;
private final String libraryName;
@@ -46,11 +45,10 @@
IAType returnType, IResultTypeComputer rtc, ExternalFunctionLanguage language,
DataverseName libraryDataverseName, String libraryName, List<String> externalIdentifier,
Map<String, String> resources, boolean deterministic) {
- super(fid, deterministic);
+ super(fid, rtc, deterministic);
this.kind = kind;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
- this.rtc = rtc;
this.language = language;
this.libraryDataverseName = libraryDataverseName;
this.libraryName = libraryName;
@@ -73,10 +71,6 @@
return returnType;
}
- public IResultTypeComputer getResultTypeComputer() {
- return rtc;
- }
-
@Override
public ExternalFunctionLanguage getLanguage() {
return language;
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/FunctionInfo.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/FunctionInfo.java
index a7377f8..f7f46f5 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/FunctionInfo.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/FunctionInfo.java
@@ -21,24 +21,23 @@
import java.util.List;
import java.util.Objects;
+import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
-public class FunctionInfo implements IFunctionInfo {
- private static final long serialVersionUID = 5460606629941107898L;
+public abstract class FunctionInfo implements IFunctionInfo {
+ private static final long serialVersionUID = 5460606629941107899L;
private final FunctionIdentifier functionIdentifier;
+ private final transient IResultTypeComputer typeComputer;
private final boolean isFunctional;
- public FunctionInfo(String namespace, String name, int arity, boolean isFunctional) {
- this(new FunctionIdentifier(namespace, name, arity), isFunctional);
- }
-
- public FunctionInfo(FunctionIdentifier functionIdentifier, boolean isFunctional) {
+ public FunctionInfo(FunctionIdentifier functionIdentifier, IResultTypeComputer typeComputer, boolean isFunctional) {
+ this.functionIdentifier = Objects.requireNonNull(functionIdentifier);
+ this.typeComputer = Objects.requireNonNull(typeComputer);
this.isFunctional = isFunctional;
- this.functionIdentifier = functionIdentifier;
}
@Override
@@ -51,6 +50,10 @@
return isFunctional;
}
+ public IResultTypeComputer getResultTypeComputer() {
+ return typeComputer;
+ }
+
/**
* @param args,
* the arguments.
@@ -62,25 +65,7 @@
}
@Override
- public int hashCode() {
- return Objects.hash(functionIdentifier.getNamespace(), functionIdentifier.getName(),
- functionIdentifier.getArity());
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof FunctionInfo)) {
- return false;
- }
- FunctionInfo info = (FunctionInfo) o;
- return functionIdentifier.equals(info.getFunctionIdentifier())
- && functionIdentifier.getArity() == info.getFunctionIdentifier().getArity();
- }
-
- @Override
public String toString() {
- return this.functionIdentifier.getNamespace() + ":" + this.functionIdentifier.getName() + "@"
- + this.functionIdentifier.getArity();
+ return functionIdentifier.toString();
}
-
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/IFunctionToDataSourceRewriter.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/IFunctionToDataSourceRewriter.java
index 2793c4d..75a9689 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/IFunctionToDataSourceRewriter.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/IFunctionToDataSourceRewriter.java
@@ -24,8 +24,6 @@
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
public interface IFunctionToDataSourceRewriter {
- public static final IFunctionToDataSourceRewriter NOOP = (o, c) -> false;
-
/**
* Replace the unnest operator by a datasource operator
*
diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
index 91752f7..6cecaec 100644
--- a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
+++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
@@ -31,6 +31,7 @@
import java.util.Map;
import java.util.Set;
+import org.apache.asterix.om.functions.BuiltinFunctionInfo;
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.asterix.om.types.ATypeTag;
@@ -43,7 +44,6 @@
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
@@ -110,50 +110,41 @@
// First, we will go over all the functions available, get their arity and type computers to know the number
// of arguments to pass for each type computer
- Map<IFunctionInfo, IResultTypeComputer> funTypeComputerMap;
+ Map<FunctionIdentifier, BuiltinFunctionInfo> registeredFunctions;
try {
- Field field = BuiltinFunctions.class.getDeclaredField("funTypeComputer");
+ Field field = BuiltinFunctions.class.getDeclaredField("registeredFunctions");
field.setAccessible(true);
- funTypeComputerMap = (HashMap<IFunctionInfo, IResultTypeComputer>) field.get(null);
+ registeredFunctions = (Map<FunctionIdentifier, BuiltinFunctionInfo>) field.get(null);
} catch (Exception ex) {
// this should never fail
throw new IllegalStateException();
}
- if (funTypeComputerMap != null) {
- // Note: If a type computer handles both known and VARARGS, VARARGS will be used
- for (HashMap.Entry<IFunctionInfo, IResultTypeComputer> entry : funTypeComputerMap.entrySet()) {
- // Some functions have a null type computer for some reason, ignore them
- if (entry.getValue() == null) {
- continue;
- }
+ // Note: If a type computer handles both known and VARARGS, VARARGS will be used
+ for (BuiltinFunctionInfo finfo : registeredFunctions.values()) {
+ FunctionIdentifier fid = finfo.getFunctionIdentifier();
+ IResultTypeComputer typeComputer = finfo.getResultTypeComputer();
- // Type computer does not exist, add it with its arity to the map
- if (typeComputerToArgsCountMap.get(entry.getValue().getClass().getSimpleName()) == null) {
- typeComputerToArgsCountMap.put(entry.getValue().getClass().getSimpleName(),
- entry.getKey().getFunctionIdentifier().getArity());
- continue;
- }
+ // Type computer does not exist, add it with its arity to the map
+ if (typeComputerToArgsCountMap.get(typeComputer.getClass().getSimpleName()) == null) {
+ typeComputerToArgsCountMap.put(typeComputer.getClass().getSimpleName(), fid.getArity());
+ continue;
+ }
- // VARARGS functions, these are kept as is, put/update, no need for any comparison
- if (entry.getKey().getFunctionIdentifier().getArity() == FunctionIdentifier.VARARGS) {
- typeComputerToArgsCountMap.put(entry.getValue().getClass().getSimpleName(),
- entry.getKey().getFunctionIdentifier().getArity());
- continue;
- }
+ // VARARGS functions, these are kept as is, put/update, no need for any comparison
+ if (fid.getArity() == FunctionIdentifier.VARARGS) {
+ typeComputerToArgsCountMap.put(typeComputer.getClass().getSimpleName(), fid.getArity());
+ continue;
+ }
- // We have it already, and it is of type VARARGS, we are not going to change it
- if (typeComputerToArgsCountMap
- .get(entry.getValue().getClass().getSimpleName()) == FunctionIdentifier.VARARGS) {
- continue;
- }
+ // We have it already, and it is of type VARARGS, we are not going to change it
+ if (typeComputerToArgsCountMap.get(typeComputer.getClass().getSimpleName()) == FunctionIdentifier.VARARGS) {
+ continue;
+ }
- // We have it already, if it has larger arity than our existing one, we will update it
- if (typeComputerToArgsCountMap.get(entry.getValue().getClass().getSimpleName()) < entry.getKey()
- .getFunctionIdentifier().getArity()) {
- typeComputerToArgsCountMap.put(entry.getValue().getClass().getSimpleName(),
- entry.getKey().getFunctionIdentifier().getArity());
- }
+ // We have it already, if it has larger arity than our existing one, we will update it
+ if (typeComputerToArgsCountMap.get(typeComputer.getClass().getSimpleName()) < fid.getArity()) {
+ typeComputerToArgsCountMap.put(typeComputer.getClass().getSimpleName(), fid.getArity());
}
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
index 0db1821..1fc200c 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
@@ -250,7 +250,7 @@
IScalarEvaluatorFactory evalFactory = fDesc.createEvaluatorFactory(
new IScalarEvaluatorFactory[] { recordEvalFactory, fldIndexEvalFactory });
IFunctionInfo finfoAccess =
- BuiltinFunctions.getAsterixFunctionInfo(BuiltinFunctions.FIELD_ACCESS_BY_INDEX);
+ BuiltinFunctions.getBuiltinFunctionInfo(BuiltinFunctions.FIELD_ACCESS_BY_INDEX);
ScalarFunctionCallExpression partitionFun = new ScalarFunctionCallExpression(finfoAccess,
new MutableObject<>(new VariableReferenceExpression(METADATA_DUMMY_VAR)),
@@ -275,7 +275,7 @@
fDesc.setImmutableStates(recType, fldName);
IScalarEvaluatorFactory evalFactory =
fDesc.createEvaluatorFactory(new IScalarEvaluatorFactory[] { recordEvalFactory });
- IFunctionInfo finfoAccess = BuiltinFunctions.getAsterixFunctionInfo(BuiltinFunctions.FIELD_ACCESS_NESTED);
+ IFunctionInfo finfoAccess = BuiltinFunctions.getBuiltinFunctionInfo(BuiltinFunctions.FIELD_ACCESS_NESTED);
ScalarFunctionCallExpression partitionFun = new ScalarFunctionCallExpression(finfoAccess,
new MutableObject<>(new VariableReferenceExpression(METADATA_DUMMY_VAR)),
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/AbstractFunctionCallExpression.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/AbstractFunctionCallExpression.java
index 1cc206f..81aac03 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/AbstractFunctionCallExpression.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/AbstractFunctionCallExpression.java
@@ -21,10 +21,12 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
@@ -54,23 +56,19 @@
public AbstractFunctionCallExpression(FunctionKind kind, IFunctionInfo finfo,
List<Mutable<ILogicalExpression>> arguments) {
- this.kind = kind;
- this.finfo = finfo;
- this.arguments = arguments;
+ this.kind = Objects.requireNonNull(kind);
+ this.finfo = Objects.requireNonNull(finfo);
+ this.arguments = Objects.requireNonNull(arguments);
}
public AbstractFunctionCallExpression(FunctionKind kind, IFunctionInfo finfo) {
- this.kind = kind;
- this.finfo = finfo;
- this.arguments = new ArrayList<Mutable<ILogicalExpression>>();
+ this(kind, finfo, new ArrayList<>());
}
public AbstractFunctionCallExpression(FunctionKind kind, IFunctionInfo finfo,
Mutable<ILogicalExpression>... expressions) {
this(kind, finfo);
- for (Mutable<ILogicalExpression> e : expressions) {
- this.arguments.add(e);
- }
+ Collections.addAll(arguments, expressions);
}
public void setOpaqueParameters(Object[] opaqueParameters) {
@@ -212,7 +210,7 @@
@Override
public int hashCode() {
- int h = finfo.hashCode();
+ int h = getFunctionIdentifier().hashCode();
for (Mutable<ILogicalExpression> e : arguments) {
h = h * 41 + e.getValue().hashCode();
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/functions/FunctionIdentifier.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/functions/FunctionIdentifier.java
index 74c1ba5..db5a959 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/functions/FunctionIdentifier.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/functions/FunctionIdentifier.java
@@ -19,6 +19,7 @@
package org.apache.hyracks.algebricks.core.algebra.functions;
import java.io.Serializable;
+import java.util.Objects;
public class FunctionIdentifier implements Serializable {
private static final long serialVersionUID = 1L;
@@ -29,20 +30,24 @@
public static final int VARARGS = -1;
- public FunctionIdentifier(String namespace, String name) {
- this(namespace, name, VARARGS);
- }
-
public FunctionIdentifier(String namespace, String name, int arity) {
this.namespace = namespace;
this.name = name;
this.arity = arity;
}
+ public String getNamespace() {
+ return namespace;
+ }
+
public String getName() {
return name;
}
+ public int getArity() {
+ return arity;
+ }
+
@Override
public boolean equals(Object o) {
if (super.equals(o)) {
@@ -50,26 +55,18 @@
}
if (o instanceof FunctionIdentifier) {
FunctionIdentifier ofi = (FunctionIdentifier) o;
- return ofi.getNamespace().equals(getNamespace()) && ofi.name.equals(name);
+ return namespace.equals(ofi.namespace) && name.equals(ofi.name) && arity == ofi.arity;
}
return false;
}
@Override
public int hashCode() {
- return name.hashCode() + namespace.hashCode();
+ return Objects.hash(namespace, name, arity);
}
@Override
public String toString() {
- return getNamespace() + ":" + name;
- }
-
- public int getArity() {
- return arity;
- }
-
- public String getNamespace() {
- return namespace;
+ return namespace + ':' + name + '#' + arity;
}
}