Merge branch 'gerrit/cheshire-cat'
Change-Id: Ic5e4d53932054abcd1fd7bfb27016861106bc462
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cross-dataverse/drop-dataverse/drop-dataverse.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cross-dataverse/drop-dataverse/drop-dataverse.2.ddl.sqlpp
similarity index 69%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cross-dataverse/drop-dataverse/drop-dataverse.2.update.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cross-dataverse/drop-dataverse/drop-dataverse.2.ddl.sqlpp
index 1f90ae9..8ecdeba 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cross-dataverse/drop-dataverse/drop-dataverse.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cross-dataverse/drop-dataverse/drop-dataverse.2.ddl.sqlpp
@@ -18,8 +18,27 @@
*/
/*
* Description : Test cross dataverse functionality
- * : create a dataset using a foreign datatype
- * : Try dropping the foreign type's dataverse
+ * : create a function using a foreign synonym
+ * : Try dropping the foreign synonym's dataverse
* Expected Res : Failure
- * Date : 2015 Steven Jacobs
*/
+
+drop dataverse b if exists;
+drop dataverse a if exists;
+
+create dataverse a;
+create dataverse b;
+
+create type a.a as {
+ id:int32
+};
+
+create dataset a.b1(a.a) primary key id;
+
+create synonym a.s1 for a.b1;
+
+create function b.f1() {
+ select * from a.s1
+};
+
+drop dataverse a;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/check-dependencies-1/check-dependencies-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/check-dependencies-1/check-dependencies-1.1.ddl.sqlpp
index c9639c4..0551845 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/check-dependencies-1/check-dependencies-1.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/check-dependencies-1/check-dependencies-1.1.ddl.sqlpp
@@ -41,6 +41,10 @@
create dataset TweetMessages(TweetMessageType)
primary key tweetid autogenerated;
+create synonym TweetMessagesSyn1 for TweetMessages;
+
+create synonym TweetMessagesSyn2 for TweetMessages;
+
create function f1(message, text){
contains(message,text)
};
@@ -49,6 +53,10 @@
(select * from TweetMessages)
};
+create function f5(){
+(select * from TweetMessagesSyn1, TweetMessagesSyn2)
+};
+
use B;
create dataset TweetMessages2(C.TweetMessageType)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-4/drop-dependency-4.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-4/drop-dependency-4.3.ddl.sqlpp
new file mode 100644
index 0000000..7943d82
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-4/drop-dependency-4.3.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under A
+ * 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 : Try to drop a functional dependency
+ * Drop a synonym that is used by a non-varargs function
+ * Expected Res : Error
+ */
+
+drop dataverse B if exists;
+drop dataverse C if exists;
+create dataverse B;
+create dataverse C;
+use C;
+
+create type TweetMessageType as closed {
+ tweetid: uuid,
+ sender_location: point,
+ send_time: datetime,
+ referred_topics: {{ string }},
+ message_text: string,
+ countA: int32,
+ countB: int32
+};
+
+create dataset TweetMessages(TweetMessageType)
+primary key tweetid autogenerated;
+
+create synonym TweetMessagesSyn for TweetMessages;
+
+use B;
+
+create function f2(place, text){
+ (select m.message_text
+ from C.TweetMessagesSyn m)
+};
+
+use C;
+drop synonym TweetMessagesSyn;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-4/drop-dependency-4.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-4/drop-dependency-4.4.ddl.sqlpp
new file mode 100644
index 0000000..7f0ff98
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-4/drop-dependency-4.4.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under A
+ * 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 : Try to drop a functional dependency
+ * Drop a synonym that is used by a varargs function
+ * Expected Res : Error
+ */
+
+drop dataverse B if exists;
+drop dataverse C if exists;
+create dataverse B;
+create dataverse C;
+use C;
+
+create type TweetMessageType as closed {
+ tweetid: uuid,
+ sender_location: point,
+ send_time: datetime,
+ referred_topics: {{ string }},
+ message_text: string,
+ countA: int32,
+ countB: int32
+};
+
+create dataset TweetMessages(TweetMessageType)
+primary key tweetid autogenerated;
+
+create synonym TweetMessagesSyn for TweetMessages;
+
+use B;
+
+create function f2(...){
+ (select m.message_text
+ from C.TweetMessagesSyn m)
+};
+
+use C;
+drop synonym TweetMessagesSyn;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-6/drop-dependency-6.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-6/drop-dependency-6.3.ddl.sqlpp
new file mode 100644
index 0000000..6cf428a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-6/drop-dependency-6.3.ddl.sqlpp
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under A
+ * 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 : Try to drop a functional dependency
+ * Drop a synonym that is used by a non-varargs function
+ * from the same dataverse
+ * Expected Res : Error
+ */
+
+drop dataverse C if exists;
+create dataverse C;
+use C;
+
+create type TweetMessageType as closed {
+ tweetid: uuid,
+ sender_location: point,
+ send_time: datetime,
+ referred_topics: {{ string }},
+ message_text: string,
+ countA: int32,
+ countB: int32
+};
+
+create dataset TweetMessages(TweetMessageType)
+primary key tweetid autogenerated;
+
+create synonym TweetMessagesSyn for TweetMessages;
+
+create function f2(place, text){
+ (select m.message_text
+ from C.TweetMessagesSyn m)
+};
+
+drop synonym TweetMessagesSyn;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-6/drop-dependency-6.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-6/drop-dependency-6.4.ddl.sqlpp
new file mode 100644
index 0000000..5198f66
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/drop-dependency-6/drop-dependency-6.4.ddl.sqlpp
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under A
+ * 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 : Try to drop a functional dependency
+ * Drop a synonym that is used by a varargs function
+ * from the same dataverse
+ * Expected Res : Error
+ */
+
+drop dataverse C if exists;
+create dataverse C;
+use C;
+
+create type TweetMessageType as closed {
+ tweetid: uuid,
+ sender_location: point,
+ send_time: datetime,
+ referred_topics: {{ string }},
+ message_text: string,
+ countA: int32,
+ countB: int32
+};
+
+create dataset TweetMessages(TweetMessageType)
+primary key tweetid autogenerated;
+
+create synonym TweetMessagesSyn for TweetMessages;
+
+create function f2(...){
+ (select m.message_text
+ from C.TweetMessagesSyn m)
+};
+
+drop synonym TweetMessagesSyn;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/check-dependencies-1/check-dependencies-1.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/check-dependencies-1/check-dependencies-1.1.adm
index 9b32c3d..2279d69 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/check-dependencies-1/check-dependencies-1.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/user-defined-functions/check-dependencies-1/check-dependencies-1.1.adm
@@ -4,3 +4,4 @@
{ "DataverseName": "C", "Name": "f2", "Dependencies": [ [ [ "C", "TweetMessages" ] ], [ [ "C", "f1", "2" ], [ "B", "f0", "2" ] ], [ ] ] }
{ "DataverseName": "C", "Name": "f3", "Dependencies": [ [ ], [ [ "C", "f2", "2" ] ], [ ] ] }
{ "DataverseName": "C", "Name": "f4", "Dependencies": [ [ [ "C", "TweetMessages" ] ], [ ], [ ] ] }
+{ "DataverseName": "C", "Name": "f5", "Dependencies": [ [ ], [ ], [ ], [ [ "C", "TweetMessagesSyn1" ], [ "C", "TweetMessagesSyn2" ] ] ] }
\ No newline at end of file
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 e0471ff..1d7f09e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -12328,6 +12328,7 @@
<compilation-unit name="drop-dataverse">
<output-dir compare="Text">drop-dataverse</output-dir>
<expected-error>ASX1147: Cannot drop dataverse: type a.a being used by dataset b.b1</expected-error>
+ <expected-error>ASX1147: Cannot drop dataverse: synonym a.s1 being used by function b.f1()</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
@@ -12471,8 +12472,10 @@
<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(...)</expected-error>
+ <expected-error>ASX1148: Cannot drop dataset C.TweetMessages being used by function B.f2(2)</expected-error>
+ <expected-error>ASX1148: Cannot drop dataset C.TweetMessages being used by function B.f2(...)</expected-error>
+ <expected-error>ASX1148: Cannot drop synonym C.TweetMessagesSyn being used by function B.f2(2)</expected-error>
+ <expected-error>ASX1148: Cannot drop synonym C.TweetMessagesSyn being used by function B.f2(...)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
@@ -12489,8 +12492,10 @@
<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(...)</expected-error>
+ <expected-error>ASX1148: Cannot drop dataset C.TweetMessages being used by function C.f2(2)</expected-error>
+ <expected-error>ASX1148: Cannot drop dataset C.TweetMessages being used by function C.f2(...)</expected-error>
+ <expected-error>ASX1148: Cannot drop synonym C.TweetMessagesSyn being used by function C.f2(2)</expected-error>
+ <expected-error>ASX1148: Cannot drop synonym C.TweetMessagesSyn being used by function C.f2(...)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
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 b491e82..7f4e078 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
@@ -276,16 +276,27 @@
Expression expression) throws CompilationException {
Set<AbstractCallExpression> 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>> datasetDependencies = new ArrayList<>();
List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
+ List<Triple<DataverseName, String, String>> typeDependencies = Collections.emptyList();
+ List<Triple<DataverseName, String, String>> synonymDependencies = new ArrayList<>();
for (AbstractCallExpression functionCall : functionCalls) {
switch (functionCall.getKind()) {
case CALL_EXPRESSION:
FunctionSignature signature = functionCall.getFunctionSignature();
if (isBuiltinDatasetFunction(signature)) {
- Pair<DataverseName, String> datasetReference =
- parseDatasetFunctionArguments((CallExpr) functionCall);
- datasourceDependencies.add(new Triple<>(datasetReference.first, datasetReference.second, null));
+ CallExpr callExpr = (CallExpr) functionCall;
+ if (callExpr.getExprList().size() > 2) {
+ // resolved via synonym -> store synonym name as a dependency
+ Pair<DataverseName, String> synonymReference = parseDatasetFunctionArguments(callExpr, 2);
+ synonymDependencies
+ .add(new Triple<>(synonymReference.first, synonymReference.second, null));
+ } else {
+ // resolved directly -> store dataset name as a dependency
+ Pair<DataverseName, String> datasetReference = parseDatasetFunctionArguments(callExpr, 0);
+ datasetDependencies
+ .add(new Triple<>(datasetReference.first, datasetReference.second, null));
+ }
} else if (BuiltinFunctions.getBuiltinFunctionInfo(signature.createFunctionIdentifier()) == null) {
functionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
Integer.toString(signature.getArity())));
@@ -299,26 +310,21 @@
functionCall.getFunctionSignature().toString(false));
}
}
- List<List<Triple<DataverseName, String, String>>> dependencies = new ArrayList<>(3);
- dependencies.add(datasourceDependencies);
- dependencies.add(functionDependencies);
- dependencies.add(Collections.emptyList());
- return dependencies;
+ return Function.createDependencies(datasetDependencies, functionDependencies, typeDependencies,
+ synonymDependencies);
}
public static List<List<Triple<DataverseName, String, String>>> getExternalFunctionDependencies(
Collection<TypeSignature> dependentTypes) {
- List<Triple<DataverseName, String, String>> datasourceDependencies = Collections.emptyList();
+ List<Triple<DataverseName, String, String>> datasetDependencies = Collections.emptyList();
List<Triple<DataverseName, String, String>> functionDependencies = Collections.emptyList();
List<Triple<DataverseName, String, String>> typeDependencies = new ArrayList<>(dependentTypes.size());
+ List<Triple<DataverseName, String, String>> synonymDependencies = Collections.emptyList();
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);
- return dependencies;
+ return Function.createDependencies(datasetDependencies, functionDependencies, typeDependencies,
+ synonymDependencies);
}
public static boolean isBuiltinDatasetFunction(FunctionSignature fs) {
@@ -328,30 +334,31 @@
public static Pair<DataverseName, String> parseDatasetFunctionArguments(CallExpr datasetFn)
throws CompilationException {
- return parseDatasetFunctionArguments(datasetFn.getExprList(), datasetFn.getSourceLocation(),
+ return parseDatasetFunctionArguments(datasetFn, 0);
+ }
+
+ public static Pair<DataverseName, String> parseDatasetFunctionArguments(CallExpr datasetFn, int startPos)
+ throws CompilationException {
+ return parseDatasetFunctionArguments(datasetFn.getExprList(), startPos, datasetFn.getSourceLocation(),
ExpressionUtils::getStringLiteral);
}
public static Pair<DataverseName, String> parseDatasetFunctionArguments(AbstractFunctionCallExpression datasetFn)
throws CompilationException {
- return parseDatasetFunctionArguments(datasetFn.getArguments(), datasetFn.getSourceLocation(),
+ return parseDatasetFunctionArguments(datasetFn.getArguments(), 0, datasetFn.getSourceLocation(),
FunctionUtil::getStringConstant);
}
- private static <T> Pair<DataverseName, String> parseDatasetFunctionArguments(List<T> datasetFnArgs,
+ private static <T> Pair<DataverseName, String> parseDatasetFunctionArguments(List<T> datasetFnArgs, int startPos,
SourceLocation sourceLoc, java.util.function.Function<T, String> argExtractFunction)
throws CompilationException {
- if (datasetFnArgs.size() != 2) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc,
- "Invalid number of arguments to dataset()");
- }
- String dataverseNameArg = argExtractFunction.apply(datasetFnArgs.get(0));
+ String dataverseNameArg = argExtractFunction.apply(datasetFnArgs.get(startPos));
if (dataverseNameArg == null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, "Invalid argument to dataset()");
}
DataverseName dataverseName = DataverseName.createFromCanonicalForm(dataverseNameArg);
- String datasetName = argExtractFunction.apply(datasetFnArgs.get(1));
+ String datasetName = argExtractFunction.apply(datasetFnArgs.get(startPos + 1));
if (datasetName == null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, "Invalid argument to dataset()");
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
index 291bcd0..8e8cfc7 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
@@ -51,6 +51,7 @@
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.api.exceptions.SourceLocation;
@@ -155,13 +156,19 @@
return null;
}
SourceLocation sourceLoc = varExpr.getSourceLocation();
- Dataset dataset = findDataset(dataverseName, datasetName, sourceLoc);
- if (dataset == null) {
+ Pair<Dataset, Boolean> datasetSynonymPair = findDataset(dataverseName, datasetName, sourceLoc);
+ if (datasetSynonymPair == null) {
throw createUnresolvableError(dataverseName, datasetName, sourceLoc);
}
- List<Expression> argList = new ArrayList<>(2);
+ Dataset dataset = datasetSynonymPair.first;
+ boolean viaSynonym = datasetSynonymPair.second;
+ List<Expression> argList = new ArrayList<>(4);
argList.add(new LiteralExpr(new StringLiteral(dataset.getDataverseName().getCanonicalForm())));
argList.add(new LiteralExpr(new StringLiteral(dataset.getDatasetName())));
+ if (viaSynonym) {
+ argList.add(new LiteralExpr(new StringLiteral(dataverseName.getCanonicalForm())));
+ argList.add(new LiteralExpr(new StringLiteral(datasetName)));
+ }
CallExpr callExpr = new CallExpr(new FunctionSignature(BuiltinFunctions.DATASET), argList);
callExpr.setSourceLocation(sourceLoc);
return callExpr;
@@ -221,16 +228,19 @@
dataverseName == null ? defaultDataverseName : dataverseName);
}
- private Dataset findDataset(DataverseName dataverseName, String datasetName, SourceLocation sourceLoc)
- throws CompilationException {
+ private Pair<Dataset, Boolean> findDataset(DataverseName dataverseName, String datasetName,
+ SourceLocation sourceLoc) throws CompilationException {
try {
- Pair<DataverseName, String> dsName =
+ Boolean viaSynonym = false;
+ Triple<DataverseName, String, Boolean> dsName =
metadataProvider.resolveDatasetNameUsingSynonyms(dataverseName, datasetName);
if (dsName != null) {
dataverseName = dsName.first;
datasetName = dsName.second;
+ viaSynonym = dsName.third;
}
- return metadataProvider.findDataset(dataverseName, datasetName);
+ Dataset dataset = metadataProvider.findDataset(dataverseName, datasetName);
+ return dataset == null ? null : new Pair<>(dataset, viaSynonym);
} catch (AlgebricksException e) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, sourceLoc, e.getMessage());
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSynonymRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSynonymRewriteVisitor.java
index ae999fd..a0ffdf2 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSynonymRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSynonymRewriteVisitor.java
@@ -28,7 +28,7 @@
import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppAstVisitor;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.api.exceptions.SourceLocation;
/**
@@ -43,7 +43,7 @@
@Override
public Void visit(LoadStatement loadStmt, MetadataProvider metadataProvider) throws CompilationException {
- Pair<DataverseName, String> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
+ Triple<DataverseName, String, Boolean> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
loadStmt.getDataverseName(), loadStmt.getDatasetName(), loadStmt.getSourceLocation());
if (dsName != null) {
loadStmt.setDataverseName(dsName.first);
@@ -54,7 +54,7 @@
@Override
public Void visit(InsertStatement insertStmt, MetadataProvider metadataProvider) throws CompilationException {
- Pair<DataverseName, String> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
+ Triple<DataverseName, String, Boolean> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
insertStmt.getDataverseName(), insertStmt.getDatasetName(), insertStmt.getSourceLocation());
if (dsName != null) {
insertStmt.setDataverseName(dsName.first);
@@ -65,7 +65,7 @@
@Override
public Void visit(DeleteStatement deleteStmt, MetadataProvider metadataProvider) throws CompilationException {
- Pair<DataverseName, String> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
+ Triple<DataverseName, String, Boolean> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
deleteStmt.getDataverseName(), deleteStmt.getDatasetName(), deleteStmt.getSourceLocation());
if (dsName != null) {
deleteStmt.setDataverseName(dsName.first);
@@ -74,7 +74,7 @@
return null;
}
- private Pair<DataverseName, String> resolveDatasetNameUsingSynonyms(MetadataProvider metadataProvider,
+ private Triple<DataverseName, String, Boolean> resolveDatasetNameUsingSynonyms(MetadataProvider metadataProvider,
DataverseName dataverseName, String datasetName, SourceLocation sourceLoc) throws CompilationException {
try {
return metadataProvider.resolveDatasetNameUsingSynonyms(dataverseName, datasetName);
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 37aae78..09709d08 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
@@ -658,12 +658,6 @@
try {
confirmDataverseCanBeDeleted(txnId, dataverseName);
- // Drop all synonyms in this dataverse.
- List<Synonym> dataverseSynonyms = getDataverseSynonyms(txnId, dataverseName);
- for (Synonym synonym : dataverseSynonyms) {
- dropSynonym(txnId, dataverseName, synonym.getSynonymName());
- }
-
// Drop all feeds and connections in this dataverse.
// Feeds may depend on datatypes and adapters
List<Feed> dataverseFeeds = getDataverseFeeds(txnId, dataverseName);
@@ -682,7 +676,7 @@
}
// Drop all functions in this dataverse.
- // Functions may depend on datatypes and libraries
+ // Functions may depend on libraries, datasets, functions, datatypes, synonyms
// 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) {
@@ -703,6 +697,12 @@
dropLibrary(txnId, lib.getDataverseName(), lib.getName());
}
+ // Drop all synonyms in this dataverse.
+ List<Synonym> dataverseSynonyms = getDataverseSynonyms(txnId, dataverseName);
+ for (Synonym synonym : dataverseSynonyms) {
+ dropSynonym(txnId, dataverseName, synonym.getSynonymName(), true);
+ }
+
// Drop all datasets and indexes in this dataverse.
// Datasets depend on datatypes
List<Dataset> dataverseDatasets = getDataverseDatasets(txnId, dataverseName);
@@ -1141,37 +1141,25 @@
}
// If a function from a DIFFERENT dataverse
- // uses datasets, functions or datatypes from this dataverse
+ // uses datasets, functions, datatypes, or synonyms from this dataverse
// throw an error
+ Function.FunctionDependencyKind[] functionDependencyKinds = Function.FunctionDependencyKind.values();
List<Function> functions = getAllFunctions(txnId);
for (Function function : functions) {
if (function.getDataverseName().equals(dataverseName)) {
continue;
}
- for (Triple<DataverseName, String, String> datasetDependency : function.getDependencies().get(0)) {
- if (datasetDependency.first.equals(dataverseName)) {
- throw new AsterixException(
- org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS,
- "dataset",
- DatasetUtil.getFullyQualifiedDisplayName(datasetDependency.first, datasetDependency.second),
- "function", function.getSignature());
- }
- }
- for (Triple<DataverseName, String, String> functionDependency : function.getDependencies().get(1)) {
- if (functionDependency.first.equals(dataverseName)) {
- throw new AsterixException(
- org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS,
- "function", new FunctionSignature(functionDependency.first, functionDependency.second,
- Integer.parseInt(functionDependency.third)),
- "function", function.getSignature());
- }
- }
- for (Triple<DataverseName, String, String> type : function.getDependencies().get(2)) {
- if (type.first.equals(dataverseName)) {
- throw new AsterixException(
- org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS,
- "type", TypeUtil.getFullyQualifiedDisplayName(type.first, type.second), "function",
- function.getSignature());
+ List<List<Triple<DataverseName, String, String>>> dependencies = function.getDependencies();
+ for (int i = 0, n = dependencies.size(); i < n; i++) {
+ for (Triple<DataverseName, String, String> dependency : dependencies.get(i)) {
+ if (dependency.first.equals(dataverseName)) {
+ Function.FunctionDependencyKind functionDependencyKind = functionDependencyKinds[i];
+ throw new AsterixException(
+ org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS,
+ functionDependencyKind.toString().toLowerCase(),
+ functionDependencyKind.getDependencyDisplayName(dependency), "function",
+ function.getSignature());
+ }
}
}
}
@@ -1195,19 +1183,7 @@
}
private void confirmFunctionCanBeDeleted(TxnId txnId, FunctionSignature signature) throws AlgebricksException {
- // If any other function uses this function, throw an error
- List<Function> functions = getAllFunctions(txnId);
- for (Function function : functions) {
- for (Triple<DataverseName, String, String> functionalDependency : function.getDependencies().get(1)) {
- if (functionalDependency.first.equals(signature.getDataverseName())
- && functionalDependency.second.equals(signature.getName())
- && functionalDependency.third.equals(Integer.toString(signature.getArity()))) {
- throw new AsterixException(
- org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_OBJECT_DEPENDENT_EXISTS,
- "function", signature, "function", function.getSignature());
- }
- }
- }
+ confirmFunctionIsUnusedByFunctions(txnId, signature);
// if any other feed connection uses this function, throw an error
List<FeedConnection> feedConnections = getAllFeedConnections(txnId);
@@ -1221,17 +1197,33 @@
}
}
- private void confirmDatasetCanBeDeleted(TxnId txnId, DataverseName dataverseName, String datasetName)
+ private void confirmFunctionIsUnusedByFunctions(TxnId txnId, FunctionSignature signature)
throws AlgebricksException {
- // If any function uses this type, throw an error
+ confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.FUNCTION, signature.getDataverseName(),
+ signature.getName(), Integer.toString(signature.getArity()));
+ }
+
+ private void confirmObjectIsUnusedByFunctions(TxnId txnId, Function.FunctionDependencyKind dependencyKind,
+ DataverseName dataverseName, String objectName, String objectArg) throws AlgebricksException {
+ // If any function uses this object, throw an error
+ int functionDependencyIdx = dependencyKind.ordinal();
List<Function> functions = getAllFunctions(txnId);
for (Function function : functions) {
- for (Triple<DataverseName, String, String> datasetDependency : function.getDependencies().get(0)) {
- if (datasetDependency.first.equals(dataverseName) && datasetDependency.second.equals(datasetName)) {
- throw new AsterixException(
- org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_OBJECT_DEPENDENT_EXISTS,
- "dataset", DatasetUtil.getFullyQualifiedDisplayName(dataverseName, datasetName), "function",
- function.getSignature());
+ List<List<Triple<DataverseName, String, String>>> functionDependencies = function.getDependencies();
+ if (functionDependencyIdx < functionDependencies.size()) {
+ List<Triple<DataverseName, String, String>> functionObjectDependencies =
+ functionDependencies.get(functionDependencyIdx);
+ if (functionObjectDependencies != null) {
+ for (Triple<DataverseName, String, String> dependency : functionObjectDependencies) {
+ if (dependency.first.equals(dataverseName) && dependency.second.equals(objectName)
+ && (objectArg == null || objectArg.equals(dependency.third))) {
+ throw new AsterixException(
+ org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_OBJECT_DEPENDENT_EXISTS,
+ dependencyKind.toString().toLowerCase(),
+ dependencyKind.getDependencyDisplayName(dependency), "function",
+ function.getSignature());
+ }
+ }
}
}
}
@@ -1256,14 +1248,29 @@
String indexConfigName = ((Index.TextIndexDetails) index.getIndexDetails()).getFullTextConfigName();
if (index.getDataverseName().equals(dataverseNameFullTextConfig)
&& !Strings.isNullOrEmpty(indexConfigName) && indexConfigName.equals(configName)) {
- throw new AlgebricksException("Cannot drop full-text config "
- + " because it is being used by index " + index.getIndexName());
+ throw new AsterixException(
+ org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_OBJECT_DEPENDENT_EXISTS,
+ "full-text config",
+ MetadataUtil.getFullyQualifiedDisplayName(dataverseNameFullTextConfig, configName),
+ "index", DatasetUtil.getFullyQualifiedDisplayName(index.getDataverseName(),
+ index.getDatasetName()) + "." + index.getIndexName());
}
}
}
}
}
+ private void confirmDatasetCanBeDeleted(TxnId txnId, DataverseName dataverseName, String datasetName)
+ throws AlgebricksException {
+ confirmDatasetIsUnusedByFunctions(txnId, dataverseName, datasetName);
+ }
+
+ private void confirmDatasetIsUnusedByFunctions(TxnId txnId, DataverseName dataverseName, String datasetName)
+ throws AlgebricksException {
+ confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.DATASET, dataverseName, datasetName,
+ null);
+ }
+
private void confirmLibraryCanBeDeleted(TxnId txnId, DataverseName dataverseName, String libraryName)
throws AlgebricksException {
confirmLibraryIsUnusedByFunctions(txnId, dataverseName, libraryName);
@@ -1347,18 +1354,8 @@
private void confirmDatatypeIsUnusedByFunctions(TxnId txnId, DataverseName dataverseName, String dataTypeName)
throws AlgebricksException {
- // If any function uses this type, throw an error
- List<Function> functions = getAllFunctions(txnId);
- 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 AsterixException(
- org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_OBJECT_DEPENDENT_EXISTS, "type",
- TypeUtil.getFullyQualifiedDisplayName(dataverseName, dataTypeName), "function",
- function.getSignature());
- }
- }
- }
+ confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.TYPE, dataverseName, dataTypeName,
+ null);
}
private void confirmFullTextFilterCanBeDeleted(TxnId txnId, DataverseName dataverseName, String fullTextFilterName)
@@ -2269,6 +2266,15 @@
@Override
public void dropSynonym(TxnId txnId, DataverseName dataverseName, String synonymName) throws AlgebricksException {
+ dropSynonym(txnId, dataverseName, synonymName, false);
+ }
+
+ private void dropSynonym(TxnId txnId, DataverseName dataverseName, String synonymName, boolean force)
+ throws AlgebricksException {
+ if (!force) {
+ confirmSynonymCanBeDeleted(txnId, dataverseName, synonymName);
+ }
+
try {
// Delete entry from the 'Synonym' dataset.
ITupleReference searchKey = createTuple(dataverseName, synonymName);
@@ -2287,6 +2293,17 @@
}
}
+ private void confirmSynonymCanBeDeleted(TxnId txnId, DataverseName dataverseName, String synonymName)
+ throws AlgebricksException {
+ confirmSynonymIsUnusedByFunctions(txnId, dataverseName, synonymName);
+ }
+
+ private void confirmSynonymIsUnusedByFunctions(TxnId txnId, DataverseName dataverseName, String synonymName)
+ throws AlgebricksException {
+ confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.SYNONYM, dataverseName, synonymName,
+ null);
+ }
+
@Override
public Synonym getSynonym(TxnId txnId, DataverseName dataverseName, String synonymName) throws AlgebricksException {
try {
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 6b3dd05..9241458 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
@@ -431,21 +431,22 @@
return MetadataManagerUtil.getDatasetIndexes(mdTxnCtx, dataverseName, datasetName);
}
- public Pair<DataverseName, String> resolveDatasetNameUsingSynonyms(DataverseName dataverseName, String datasetName)
- throws AlgebricksException {
+ public Triple<DataverseName, String, Boolean> resolveDatasetNameUsingSynonyms(DataverseName dataverseName,
+ String datasetName) throws AlgebricksException {
DataverseName dvName = getActiveDataverseName(dataverseName);
if (dvName == null) {
return null;
}
+ Synonym synonym = null;
while (MetadataManagerUtil.findDataset(mdTxnCtx, dvName, datasetName) == null) {
- Synonym synonym = findSynonym(dvName, datasetName);
+ synonym = findSynonym(dvName, datasetName);
if (synonym == null) {
return null;
}
dvName = synonym.getObjectDataverseName();
datasetName = synonym.getObjectName();
}
- return new Pair<>(dvName, datasetName);
+ return new Triple<>(dvName, datasetName, synonym != null);
}
public Synonym findSynonym(DataverseName dataverseName, String synonymName) throws AlgebricksException {
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 968cf14..3cd4346 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Function.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Function.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.metadata.entities;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -27,6 +28,9 @@
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.metadata.MetadataCache;
import org.apache.asterix.metadata.api.IMetadataEntity;
+import org.apache.asterix.metadata.utils.DatasetUtil;
+import org.apache.asterix.metadata.utils.MetadataUtil;
+import org.apache.asterix.metadata.utils.TypeUtil;
import org.apache.asterix.om.types.TypeSignature;
import org.apache.hyracks.algebricks.common.utils.Triple;
@@ -159,4 +163,39 @@
public Function dropFromCache(MetadataCache cache) {
return cache.dropFunction(this);
}
+
+ public static List<List<Triple<DataverseName, String, String>>> createDependencies(
+ List<Triple<DataverseName, String, String>> datasetDependencies,
+ List<Triple<DataverseName, String, String>> functionDependencies,
+ List<Triple<DataverseName, String, String>> typeDependencies,
+ List<Triple<DataverseName, String, String>> synonymDependencies) {
+ List<List<Triple<DataverseName, String, String>>> depList = new ArrayList<>(4);
+ depList.add(datasetDependencies);
+ depList.add(functionDependencies);
+ depList.add(typeDependencies);
+ if (!synonymDependencies.isEmpty()) {
+ depList.add(synonymDependencies);
+ }
+ return depList;
+ }
+
+ public enum FunctionDependencyKind {
+ DATASET(dependency -> DatasetUtil.getFullyQualifiedDisplayName(dependency.first, dependency.second)),
+ FUNCTION(
+ dependency -> new FunctionSignature(dependency.first, dependency.second,
+ Integer.parseInt(dependency.third)).toString()),
+ TYPE(dependency -> TypeUtil.getFullyQualifiedDisplayName(dependency.first, dependency.second)),
+ SYNONYM(dependency -> MetadataUtil.getFullyQualifiedDisplayName(dependency.first, dependency.second));
+
+ private final java.util.function.Function<Triple<DataverseName, String, String>, String> dependencyDisplayNameAccessor;
+
+ FunctionDependencyKind(
+ java.util.function.Function<Triple<DataverseName, String, String>, String> dependencyDisplayNameAccessor) {
+ this.dependencyDisplayNameAccessor = dependencyDisplayNameAccessor;
+ }
+
+ public String getDependencyDisplayName(Triple<DataverseName, String, String> dependency) {
+ return dependencyDisplayNameAccessor.apply(dependency);
+ }
+ }
}