[NO ISSUE][COMP] Support views
- user model changes: yes
- storage format changes: no
- interface changes: no
Details:
- Add CREATE VIEW, DROP VIEW statements
- Add testcases
- Update documentation
Change-Id: I802415e56b3a15265c47142fe8986959d6bec266
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/11124
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java
index 6f07718..ac7fabe 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java
@@ -46,6 +46,7 @@
import org.apache.asterix.lang.common.statement.CreateFunctionStatement;
import org.apache.asterix.lang.common.statement.CreateLibraryStatement;
import org.apache.asterix.lang.common.statement.CreateSynonymStatement;
+import org.apache.asterix.lang.common.statement.CreateViewStatement;
import org.apache.asterix.lang.common.statement.DatasetDecl;
import org.apache.asterix.lang.common.statement.DataverseDropStatement;
import org.apache.asterix.lang.common.statement.DeleteStatement;
@@ -341,6 +342,17 @@
}
break;
+ case CREATE_VIEW:
+ CreateViewStatement viewCreateStmt = (CreateViewStatement) stmt;
+ if (viewCreateStmt.getDataverseName() != null) {
+ dataverseName = viewCreateStmt.getDataverseName();
+ }
+ invalidOperation = isMetadataDataverse(dataverseName);
+ if (invalidOperation) {
+ message = String.format(BAD_DATAVERSE_OBJECT_DDL_MESSAGE, "create", "view", dataverseName);
+ }
+ break;
+
case CREATE_FEED:
CreateFeedStatement feedCreateStmt = (CreateFeedStatement) stmt;
if (feedCreateStmt.getDataverseName() != null) {
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
index d60b791..8a91059 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
@@ -36,7 +36,6 @@
import org.apache.asterix.common.exceptions.ACIDException;
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.common.metadata.DataverseName;
-import org.apache.asterix.lang.common.base.IStatementRewriter;
import org.apache.asterix.lang.common.base.Statement;
import org.apache.asterix.lang.common.statement.Query;
import org.apache.asterix.metadata.declared.MetadataProvider;
@@ -272,8 +271,6 @@
* The data modification statement when the query results in a modification to a dataset
* @param statementParameters
* Statement parameters
- * @param statementRewriter
- * The statement rewriter
* @param requestParameters
* The request parameters
* @return the compiled {@code JobSpecification}
@@ -284,8 +281,7 @@
*/
JobSpecification rewriteCompileQuery(IClusterInfoCollector clusterInfoCollector, MetadataProvider metadataProvider,
Query query, ICompiledDmlStatement dmlStatement, Map<String, IAObject> statementParameters,
- IStatementRewriter statementRewriter, IRequestParameters requestParameters)
- throws RemoteException, AlgebricksException, ACIDException;
+ IRequestParameters requestParameters) throws RemoteException, AlgebricksException, ACIDException;
/**
* returns the active dataverse for an entity or a statement
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 c053ab9..7f3644d 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
@@ -68,6 +68,7 @@
import org.apache.asterix.lang.common.literal.StringLiteral;
import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.statement.ViewDecl;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.OperatorType;
import org.apache.asterix.lang.common.struct.QuantifiedPair;
@@ -977,8 +978,17 @@
}
@Override
- public Pair<ILogicalOperator, LogicalVariable> visit(FunctionDecl fd, Mutable<ILogicalOperator> tupSource) {
- throw new IllegalStateException("Function declarations should be inlined at AST rewriting phase.");
+ public Pair<ILogicalOperator, LogicalVariable> visit(FunctionDecl fd, Mutable<ILogicalOperator> tupSource)
+ throws CompilationException {
+ // Function declarations should be inlined at AST rewriting phase
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, fd.getSourceLocation(), fd.getSignature());
+ }
+
+ @Override
+ public Pair<ILogicalOperator, LogicalVariable> visit(ViewDecl vd, Mutable<ILogicalOperator> tupSource)
+ throws CompilationException {
+ // View declarations should be inlined at AST rewriting phase
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, vd.getSourceLocation(), vd.getViewName());
}
@Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index 326ddcc..e46177a 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -64,6 +64,7 @@
import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.statement.Query;
import org.apache.asterix.lang.common.statement.StartFeedStatement;
+import org.apache.asterix.lang.common.statement.ViewDecl;
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.lang.sqlpp.rewrites.SqlppQueryRewriter;
@@ -186,9 +187,9 @@
}
public Pair<IReturningStatement, Integer> reWriteQuery(List<FunctionDecl> declaredFunctions,
- MetadataProvider metadataProvider, IReturningStatement q, SessionOutput output,
- boolean allowNonStoredUdfCalls, boolean inlineUdfs, Collection<VarIdentifier> externalVars,
- IWarningCollector warningCollector) throws CompilationException {
+ List<ViewDecl> declaredViews, MetadataProvider metadataProvider, IReturningStatement q,
+ SessionOutput output, boolean allowNonStoredUdfCalls, boolean inlineUdfsAndViews,
+ Collection<VarIdentifier> externalVars, IWarningCollector warningCollector) throws CompilationException {
if (q == null) {
return null;
}
@@ -197,9 +198,9 @@
generateExpressionTree(q);
}
IQueryRewriter rw = rewriterFactory.createQueryRewriter();
- LangRewritingContext rwCtx =
- new LangRewritingContext(metadataProvider, declaredFunctions, warningCollector, q.getVarCounter());
- rw.rewrite(rwCtx, q, allowNonStoredUdfCalls, inlineUdfs, externalVars);
+ LangRewritingContext rwCtx = new LangRewritingContext(metadataProvider, declaredFunctions, declaredViews,
+ warningCollector, q.getVarCounter());
+ rw.rewrite(rwCtx, q, allowNonStoredUdfCalls, inlineUdfsAndViews, externalVars);
return new Pair<>(q, q.getVarCounter());
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java
index f1652ea..58a37bd 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RebalanceApiServlet.java
@@ -45,9 +45,12 @@
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.Dataset;
import org.apache.asterix.metadata.entities.Dataverse;
+import org.apache.asterix.metadata.utils.DatasetUtil;
import org.apache.asterix.metadata.utils.MetadataConstants;
import org.apache.asterix.rebalance.NoOpDatasetRebalanceCallback;
import org.apache.asterix.utils.RebalanceUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.api.client.IHyracksClientConnection;
import org.apache.hyracks.http.api.IServletRequest;
@@ -181,7 +184,7 @@
if (datasetName == null) {
// Rebalances datasets in a given dataverse or all non-metadata datasets.
- List<Dataset> datasets = dataverseName == null ? getAllDatasetsForRebalance()
+ Iterable<Dataset> datasets = dataverseName == null ? getAllDatasetsForRebalance()
: getAllDatasetsForRebalance(dataverseName);
for (Dataset dataset : datasets) {
// By the time rebalanceDataset(...) is called, the dataset could have been dropped.
@@ -212,8 +215,8 @@
}
// Lists all datasets that should be rebalanced in a given datavserse.
- private List<Dataset> getAllDatasetsForRebalance(DataverseName dataverseName) throws Exception {
- List<Dataset> datasets;
+ private Iterable<Dataset> getAllDatasetsForRebalance(DataverseName dataverseName) throws Exception {
+ Iterable<Dataset> datasets;
MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
try {
datasets = getDatasetsInDataverseForRebalance(dataverseName, mdTxnCtx);
@@ -226,13 +229,13 @@
}
// Lists all datasets that should be rebalanced.
- private List<Dataset> getAllDatasetsForRebalance() throws Exception {
+ private Iterable<Dataset> getAllDatasetsForRebalance() throws Exception {
List<Dataset> datasets = new ArrayList<>();
MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
try {
List<Dataverse> dataverses = MetadataManager.INSTANCE.getDataverses(mdTxnCtx);
for (Dataverse dv : dataverses) {
- datasets.addAll(getDatasetsInDataverseForRebalance(dv.getDataverseName(), mdTxnCtx));
+ CollectionUtils.addAll(datasets, getDatasetsInDataverseForRebalance(dv.getDataverseName(), mdTxnCtx));
}
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
} catch (Exception e) {
@@ -243,10 +246,11 @@
}
// Gets all datasets in a dataverse for the rebalance operation, with a given metadata transaction context.
- private List<Dataset> getDatasetsInDataverseForRebalance(DataverseName dvName, MetadataTransactionContext mdTxnCtx)
- throws Exception {
+ private Iterable<Dataset> getDatasetsInDataverseForRebalance(DataverseName dvName,
+ MetadataTransactionContext mdTxnCtx) throws Exception {
return MetadataConstants.METADATA_DATAVERSE_NAME.equals(dvName) ? Collections.emptyList()
- : MetadataManager.INSTANCE.getDataverseDatasets(mdTxnCtx, dvName);
+ : IterableUtils.filteredIterable(MetadataManager.INSTANCE.getDataverseDatasets(mdTxnCtx, dvName),
+ DatasetUtil::isNotView);
}
// Rebalances a given dataset.
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java
index 6944b25..e25c530 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/function/DatasetRewriter.java
@@ -24,15 +24,16 @@
import java.util.ArrayList;
import java.util.List;
-import org.apache.asterix.common.config.DatasetConfig.DatasetType;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.metadata.declared.DataSource;
import org.apache.asterix.metadata.declared.DataSourceId;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.Dataset;
+import org.apache.asterix.metadata.utils.DatasetUtil;
import org.apache.asterix.om.functions.IFunctionToDataSourceRewriter;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.asterix.om.types.ARecordType;
@@ -41,7 +42,6 @@
import org.apache.asterix.optimizer.rules.util.EquivalenceClassUtils;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
@@ -75,15 +75,25 @@
MetadataProvider metadataProvider = (MetadataProvider) context.getMetadataProvider();
Dataset dataset = fetchDataset(metadataProvider, f);
- DataSourceId dsid = new DataSourceId(dataset.getDataverseName(), dataset.getDatasetName());
List<LogicalVariable> variables = new ArrayList<>();
- if (dataset.getDatasetType() == DatasetType.INTERNAL) {
- int numPrimaryKeys = dataset.getPrimaryKeys().size();
- for (int i = 0; i < numPrimaryKeys; i++) {
- variables.add(context.newVar());
- }
+ switch (dataset.getDatasetType()) {
+ case INTERNAL:
+ int numPrimaryKeys = dataset.getPrimaryKeys().size();
+ for (int i = 0; i < numPrimaryKeys; i++) {
+ variables.add(context.newVar());
+ }
+ break;
+ case EXTERNAL:
+ break;
+ default:
+ // VIEWS are not expected at this point
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, unnest.getSourceLocation(),
+ "Unexpected dataset type " + dataset.getDatasetType() + " for dataset "
+ + DatasetUtil.getFullyQualifiedDisplayName(dataset));
}
variables.add(unnest.getVariable());
+
+ DataSourceId dsid = new DataSourceId(dataset.getDataverseName(), dataset.getDatasetName());
DataSource dataSource = metadataProvider.findDataSource(dsid);
boolean hasMeta = dataSource.hasMeta();
if (hasMeta) {
@@ -132,9 +142,9 @@
public static Dataset fetchDataset(MetadataProvider metadataProvider, AbstractFunctionCallExpression datasetFnCall)
throws CompilationException {
- Pair<DataverseName, String> datasetReference = FunctionUtil.parseDatasetFunctionArguments(datasetFnCall);
- DataverseName dataverseName = datasetReference.first;
- String datasetName = datasetReference.second;
+ DatasetFullyQualifiedName datasetReference = FunctionUtil.parseDatasetFunctionArguments(datasetFnCall);
+ DataverseName dataverseName = datasetReference.getDataverseName();
+ String datasetName = datasetReference.getDatasetName();
Dataset dataset;
try {
dataset = metadataProvider.findDataset(dataverseName, datasetName);
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 1fab5d0..3571d88 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
@@ -85,6 +85,7 @@
import org.apache.asterix.common.external.IDataSourceAdapter;
import org.apache.asterix.common.functions.ExternalFunctionLanguage;
import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.common.metadata.IMetadataLockUtil;
import org.apache.asterix.common.utils.JobUtils;
@@ -97,17 +98,14 @@
import org.apache.asterix.external.operators.FeedIntakeOperatorNodePushable;
import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.asterix.external.util.ExternalDataUtils;
-import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.base.IReturningStatement;
import org.apache.asterix.lang.common.base.IRewriterFactory;
import org.apache.asterix.lang.common.base.IStatementRewriter;
import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.lang.common.expression.CallExpr;
import org.apache.asterix.lang.common.expression.IndexedTypeExpression;
-import org.apache.asterix.lang.common.expression.LiteralExpr;
import org.apache.asterix.lang.common.expression.TypeExpression;
import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
-import org.apache.asterix.lang.common.literal.MissingLiteral;
import org.apache.asterix.lang.common.statement.AdapterDropStatement;
import org.apache.asterix.lang.common.statement.CompactStatement;
import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
@@ -121,6 +119,7 @@
import org.apache.asterix.lang.common.statement.CreateIndexStatement;
import org.apache.asterix.lang.common.statement.CreateLibraryStatement;
import org.apache.asterix.lang.common.statement.CreateSynonymStatement;
+import org.apache.asterix.lang.common.statement.CreateViewStatement;
import org.apache.asterix.lang.common.statement.DatasetDecl;
import org.apache.asterix.lang.common.statement.DataverseDecl;
import org.apache.asterix.lang.common.statement.DataverseDropStatement;
@@ -149,10 +148,13 @@
import org.apache.asterix.lang.common.statement.SynonymDropStatement;
import org.apache.asterix.lang.common.statement.TypeDecl;
import org.apache.asterix.lang.common.statement.TypeDropStatement;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.lang.common.statement.ViewDropStatement;
import org.apache.asterix.lang.common.statement.WriteStatement;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.lang.common.util.FunctionUtil;
+import org.apache.asterix.lang.common.util.ViewUtil;
import org.apache.asterix.metadata.IDatasetDetails;
import org.apache.asterix.metadata.MetadataManager;
import org.apache.asterix.metadata.MetadataTransactionContext;
@@ -178,6 +180,7 @@
import org.apache.asterix.metadata.entities.Library;
import org.apache.asterix.metadata.entities.NodeGroup;
import org.apache.asterix.metadata.entities.Synonym;
+import org.apache.asterix.metadata.entities.ViewDetails;
import org.apache.asterix.metadata.feeds.FeedMetadataUtil;
import org.apache.asterix.metadata.functions.ExternalFunctionCompilerUtil;
import org.apache.asterix.metadata.lock.ExternalDatasetsRegistry;
@@ -419,6 +422,12 @@
case SYNONYM_DROP:
handleDropSynonymStatement(metadataProvider, stmt);
break;
+ case CREATE_VIEW:
+ handleCreateViewStatement(metadataProvider, stmt, stmtRewriter, requestParameters);
+ break;
+ case VIEW_DROP:
+ handleViewDropStatement(metadataProvider, stmt);
+ break;
case LOAD:
handleLoadStatement(metadataProvider, stmt, hcc);
break;
@@ -731,8 +740,12 @@
}
IDatasetDetails datasetDetails;
- Dataset ds = metadataProvider.findDataset(dataverseName, datasetName);
+ Dataset ds = metadataProvider.findDataset(dataverseName, datasetName, true);
if (ds != null) {
+ if (ds.getDatasetType() == DatasetType.VIEW) {
+ throw new CompilationException(ErrorCode.VIEW_EXISTS, sourceLoc,
+ DatasetUtil.getFullyQualifiedDisplayName(ds));
+ }
if (dd.getIfNotExists()) {
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
return;
@@ -1844,23 +1857,31 @@
List<Dataset> datasets = MetadataManager.INSTANCE.getDataverseDatasets(mdTxnCtx, dataverseName);
for (Dataset dataset : datasets) {
String datasetName = dataset.getDatasetName();
- List<Index> indexes = MetadataManager.INSTANCE.getDatasetIndexes(mdTxnCtx, dataverseName, datasetName);
DatasetType dsType = dataset.getDatasetType();
- if (dsType == DatasetType.INTERNAL) {
- for (Index index : indexes) {
- jobsToExecute.add(IndexUtil.buildDropIndexJobSpec(index, metadataProvider, dataset, sourceLoc));
- }
- } else if (dsType == DatasetType.EXTERNAL) {
- for (Index index : indexes) {
- if (ExternalIndexingOperations.isFileIndex(index)) {
- jobsToExecute.add(
- ExternalIndexingOperations.buildDropFilesIndexJobSpec(metadataProvider, dataset));
- } else {
+ switch (dsType) {
+ case INTERNAL:
+ List<Index> indexes =
+ MetadataManager.INSTANCE.getDatasetIndexes(mdTxnCtx, dataverseName, datasetName);
+ for (Index index : indexes) {
jobsToExecute
.add(IndexUtil.buildDropIndexJobSpec(index, metadataProvider, dataset, sourceLoc));
}
- }
- externalDatasetsToDeregister.add(dataset);
+ break;
+ case EXTERNAL:
+ indexes = MetadataManager.INSTANCE.getDatasetIndexes(mdTxnCtx, dataverseName, datasetName);
+ for (Index index : indexes) {
+ if (ExternalIndexingOperations.isFileIndex(index)) {
+ jobsToExecute.add(ExternalIndexingOperations
+ .buildDropFilesIndexJobSpec(metadataProvider, dataset));
+ } else {
+ jobsToExecute.add(
+ IndexUtil.buildDropIndexJobSpec(index, metadataProvider, dataset, sourceLoc));
+ }
+ }
+ externalDatasetsToDeregister.add(dataset);
+ break;
+ case VIEW:
+ break;
}
}
@@ -2009,7 +2030,7 @@
throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverseName);
}
}
- ds = metadataProvider.findDataset(dataverseName, datasetName);
+ ds = metadataProvider.findDataset(dataverseName, datasetName, true);
if (ds == null) {
if (ifExists) {
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx.getValue());
@@ -2018,6 +2039,9 @@
throw new CompilationException(ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE, sourceLoc, datasetName,
dataverseName);
}
+ } else if (ds.getDatasetType() == DatasetType.VIEW) {
+ throw new CompilationException(ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE, sourceLoc, datasetName,
+ dataverseName);
}
validateDatasetState(metadataProvider, ds, sourceLoc);
@@ -2412,6 +2436,140 @@
}
}
+ public void handleCreateViewStatement(MetadataProvider metadataProvider, Statement stmt,
+ IStatementRewriter stmtRewriter, IRequestParameters requestParameters) throws Exception {
+ CreateViewStatement cvs = (CreateViewStatement) stmt;
+ metadataProvider.validateDatabaseObjectName(cvs.getDataverseName(), cvs.getViewName(),
+ stmt.getSourceLocation());
+ DataverseName dataverseName = getActiveDataverseName(cvs.getDataverseName());
+ lockUtil.createDatasetBegin(lockManager, metadataProvider.getLocks(), dataverseName, cvs.getViewName(),
+ MetadataBuiltinEntities.ANY_OBJECT_DATATYPE.getDataverseName(),
+ MetadataBuiltinEntities.ANY_OBJECT_DATATYPE.getDatatypeName(), false, null, null, false, null, null,
+ true, DatasetType.VIEW, null);
+ try {
+ doCreateView(metadataProvider, cvs, dataverseName, cvs.getViewName(), stmtRewriter, requestParameters);
+ } finally {
+ metadataProvider.getLocks().unlock();
+ metadataProvider.setDefaultDataverse(activeDataverse);
+ }
+ }
+
+ protected void doCreateView(MetadataProvider metadataProvider, CreateViewStatement cvs, DataverseName dataverseName,
+ String viewName, IStatementRewriter stmtRewriter, IRequestParameters requestParameters) throws Exception {
+ SourceLocation sourceLoc = cvs.getSourceLocation();
+ MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
+ metadataProvider.setMetadataTxnContext(mdTxnCtx);
+ try {
+ Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, dataverseName);
+ if (dv == null) {
+ throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverseName);
+ }
+ Dataset existingDataset = MetadataManager.INSTANCE.getDataset(mdTxnCtx, dataverseName, viewName);
+ if (existingDataset != null) {
+ if (DatasetUtil.isNotView(existingDataset)) {
+ throw new CompilationException(ErrorCode.DATASET_EXISTS, sourceLoc,
+ existingDataset.getDatasetName(), existingDataset.getDataverseName());
+ }
+ if (cvs.getIfNotExists()) {
+ MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
+ return;
+ } else if (!cvs.getReplaceIfExists()) {
+ throw new CompilationException(ErrorCode.VIEW_EXISTS, sourceLoc,
+ existingDataset.getDatasetFullyQualifiedName());
+ }
+ }
+
+ // Check whether the view is usable:
+ // create a view declaration for this function,
+ // and a query body that queries this view:
+ ViewDecl viewDecl =
+ new ViewDecl(new DatasetFullyQualifiedName(dataverseName, viewName), cvs.getViewBodyExpression());
+ viewDecl.setSourceLocation(sourceLoc);
+ IQueryRewriter queryRewriter = rewriterFactory.createQueryRewriter();
+ Query wrappedQuery = queryRewriter.createViewAccessorQuery(viewDecl);
+ metadataProvider.setDefaultDataverse(dv);
+ apiFramework.reWriteQuery(declaredFunctions, Collections.singletonList(viewDecl), metadataProvider,
+ wrappedQuery, sessionOutput, false, false, Collections.emptyList(), warningCollector);
+
+ List<List<Triple<DataverseName, String, String>>> dependencies =
+ ViewUtil.getViewDependencies(viewDecl, queryRewriter);
+
+ ViewDetails viewDetails = new ViewDetails(cvs.getViewBody(), dependencies);
+
+ Dataset view =
+ new Dataset(dataverseName, viewName, MetadataBuiltinEntities.ANY_OBJECT_DATATYPE.getDataverseName(),
+ MetadataBuiltinEntities.ANY_OBJECT_DATATYPE.getDatatypeName(),
+ MetadataConstants.METADATA_NODEGROUP_NAME, "", Collections.emptyMap(), viewDetails,
+ Collections.emptyMap(), DatasetType.VIEW, 0, MetadataUtil.PENDING_NO_OP);
+ if (existingDataset == null) {
+ MetadataManager.INSTANCE.addDataset(mdTxnCtx, view);
+ } else {
+ MetadataManager.INSTANCE.updateDataset(mdTxnCtx, view);
+ }
+ MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
+ } catch (Exception e) {
+ abort(e, e, mdTxnCtx);
+ throw e;
+ }
+ }
+
+ public void handleViewDropStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
+ ViewDropStatement stmtDrop = (ViewDropStatement) stmt;
+ SourceLocation sourceLoc = stmtDrop.getSourceLocation();
+ String viewName = stmtDrop.getViewName().getValue();
+ metadataProvider.validateDatabaseObjectName(stmtDrop.getDataverseName(), viewName, sourceLoc);
+ DataverseName dataverseName = getActiveDataverseName(stmtDrop.getDataverseName());
+ lockUtil.dropDatasetBegin(lockManager, metadataProvider.getLocks(), dataverseName, viewName);
+ try {
+ doDropView(metadataProvider, stmtDrop, dataverseName, viewName);
+ } finally {
+ metadataProvider.getLocks().unlock();
+ ExternalDatasetsRegistry.INSTANCE.releaseAcquiredLocks(metadataProvider);
+ }
+ }
+
+ protected boolean doDropView(MetadataProvider metadataProvider, ViewDropStatement stmtViewDrop,
+ DataverseName dataverseName, String viewName) throws Exception {
+ SourceLocation sourceLoc = stmtViewDrop.getSourceLocation();
+ MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
+ metadataProvider.setMetadataTxnContext(mdTxnCtx);
+ try {
+ // Check if the dataverse exists
+ Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, dataverseName);
+ if (dv == null) {
+ if (stmtViewDrop.getIfExists()) {
+ if (warningCollector.shouldWarn()) {
+ warningCollector.warn(Warning.of(stmtViewDrop.getSourceLocation(), ErrorCode.UNKNOWN_DATAVERSE,
+ dataverseName));
+ }
+ MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
+ return false;
+ } else {
+ throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, sourceLoc, dataverseName);
+ }
+ }
+ Dataset dataset = metadataProvider.findDataset(dataverseName, viewName, true);
+ if (dataset == null) {
+ if (stmtViewDrop.getIfExists()) {
+ MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
+ return false;
+ } else {
+ throw new CompilationException(ErrorCode.UNKNOWN_VIEW, sourceLoc,
+ DatasetUtil.getFullyQualifiedDisplayName(dataverseName, viewName));
+ }
+ } else if (DatasetUtil.isNotView(dataset)) {
+ throw new CompilationException(ErrorCode.UNKNOWN_VIEW, sourceLoc,
+ DatasetUtil.getFullyQualifiedDisplayName(dataverseName, viewName));
+ }
+ MetadataManager.INSTANCE.dropDataset(mdTxnCtx, dataverseName, viewName, false);
+ MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
+ return true;
+ } catch (Exception e) {
+ abort(e, e, mdTxnCtx);
+ throw e;
+ }
+ }
+
protected void handleDeclareFunctionStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
FunctionDecl fds = (FunctionDecl) stmt;
FunctionSignature signature = fds.getSignature();
@@ -2475,6 +2633,7 @@
existingInlineTypes = Collections.emptyList();
}
+ IQueryRewriter queryRewriter = rewriterFactory.createQueryRewriter();
Map<TypeSignature, Datatype> newInlineTypes;
Function function;
if (cfs.isExternal()) {
@@ -2514,7 +2673,7 @@
newInlineTypes.put(paramTypeSignature, paramInlineTypeEntity);
}
VarIdentifier paramName = paramPair.getFirst();
- paramNames.add(stmtRewriter.toFunctionParameterName(paramName));
+ paramNames.add(queryRewriter.toFunctionParameterName(paramName));
}
TypeSignature returnTypeSignature;
@@ -2569,7 +2728,7 @@
for (Pair<VarIdentifier, TypeExpression> paramPair : paramList) {
VarIdentifier paramName = paramPair.getFirst();
paramVars.add(paramName);
- paramNames.add(stmtRewriter.toFunctionParameterName(paramName));
+ paramNames.add(queryRewriter.toFunctionParameterName(paramName));
if (paramPair.getSecond() != null) {
throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
paramName.toString());
@@ -2581,25 +2740,17 @@
// and a query body calls this function with each argument set to 'missing'
FunctionDecl fd = new FunctionDecl(functionSignature, paramVars, cfs.getFunctionBodyExpression(), true);
fd.setSourceLocation(sourceLoc);
- CallExpr fcall = new CallExpr(functionSignature,
- Collections.nCopies(paramVars.size(), new LiteralExpr(MissingLiteral.INSTANCE)));
- fcall.setSourceLocation(sourceLoc);
- metadataProvider.setDefaultDataverse(dv);
- Query wrappedQuery = new Query(false);
- wrappedQuery.setSourceLocation(sourceLoc);
- wrappedQuery.setBody(fcall);
- wrappedQuery.setTopLevel(false);
- List<FunctionDecl> fdList = new ArrayList<>(declaredFunctions);
+
+ Query wrappedQuery = queryRewriter.createFunctionAccessorQuery(fd);
+ List<FunctionDecl> fdList = new ArrayList<>(declaredFunctions.size() + 1);
+ fdList.addAll(declaredFunctions);
fdList.add(fd);
- apiFramework.reWriteQuery(fdList, metadataProvider, wrappedQuery, sessionOutput, false, false,
+ metadataProvider.setDefaultDataverse(dv);
+ apiFramework.reWriteQuery(fdList, null, metadataProvider, wrappedQuery, sessionOutput, false, false,
Collections.emptyList(), warningCollector);
- Expression fdNormBody = fd.getNormalizedFuncBody();
- if (fdNormBody == null) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc,
- functionSignature.toString());
- }
+
List<List<Triple<DataverseName, String, String>>> dependencies =
- FunctionUtil.getFunctionDependencies(rewriterFactory.createQueryRewriter(), fdNormBody);
+ FunctionUtil.getFunctionDependencies(fd, queryRewriter);
newInlineTypes = Collections.emptyMap();
function = new Function(functionSignature, paramNames, null, null, cfs.getFunctionBody(),
@@ -2630,14 +2781,14 @@
}
MetadataManager.INSTANCE.updateFunction(mdTxnCtx, function);
}
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info("Installed function: " + functionSignature);
- }
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
} catch (Exception e) {
abort(e, e, mdTxnCtx);
throw e;
}
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("Installed function: " + functionSignature);
+ }
}
private Triple<TypeSignature, TypeSignature, Datatype> translateFunctionParameterType(
@@ -3231,7 +3382,7 @@
try {
metadataProvider.setWriteTransaction(true);
final JobSpecification jobSpec =
- rewriteCompileInsertUpsert(hcc, metadataProvider, stmtInsertUpsert, stmtParams, stmtRewriter);
+ rewriteCompileInsertUpsert(hcc, metadataProvider, stmtInsertUpsert, stmtParams);
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
bActiveTxn = false;
return jobSpec;
@@ -3286,8 +3437,8 @@
CompiledDeleteStatement clfrqs = new CompiledDeleteStatement(stmtDelete.getVariableExpr(), dataverseName,
datasetName, stmtDelete.getCondition(), stmtDelete.getVarCounter(), stmtDelete.getQuery());
clfrqs.setSourceLocation(stmt.getSourceLocation());
- JobSpecification jobSpec = rewriteCompileQuery(hcc, metadataProvider, clfrqs.getQuery(), clfrqs, stmtParams,
- stmtRewriter, null);
+ JobSpecification jobSpec =
+ rewriteCompileQuery(hcc, metadataProvider, clfrqs.getQuery(), clfrqs, stmtParams, null);
afterCompile();
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
@@ -3310,13 +3461,13 @@
@Override
public JobSpecification rewriteCompileQuery(IClusterInfoCollector clusterInfoCollector,
MetadataProvider metadataProvider, Query query, ICompiledDmlStatement stmt,
- Map<String, IAObject> stmtParams, IStatementRewriter stmtRewriter, IRequestParameters requestParameters)
+ Map<String, IAObject> stmtParams, IRequestParameters requestParameters)
throws AlgebricksException, ACIDException {
- Map<VarIdentifier, IAObject> externalVars = createExternalVariables(stmtParams, stmtRewriter);
+ Map<VarIdentifier, IAObject> externalVars = createExternalVariables(stmtParams);
// Query Rewriting (happens under the same ongoing metadata transaction)
- Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
+ Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions, null,
metadataProvider, query, sessionOutput, true, true, externalVars.keySet(), warningCollector);
// Query Compilation (happens under the same ongoing metadata transaction)
@@ -3326,14 +3477,14 @@
}
private JobSpecification rewriteCompileInsertUpsert(IClusterInfoCollector clusterInfoCollector,
- MetadataProvider metadataProvider, InsertStatement insertUpsert, Map<String, IAObject> stmtParams,
- IStatementRewriter stmtRewriter) throws AlgebricksException, ACIDException {
+ MetadataProvider metadataProvider, InsertStatement insertUpsert, Map<String, IAObject> stmtParams)
+ throws AlgebricksException, ACIDException {
SourceLocation sourceLoc = insertUpsert.getSourceLocation();
- Map<VarIdentifier, IAObject> externalVars = createExternalVariables(stmtParams, stmtRewriter);
+ Map<VarIdentifier, IAObject> externalVars = createExternalVariables(stmtParams);
// Insert/upsert statement rewriting (happens under the same ongoing metadata transaction)
- Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
+ Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions, null,
metadataProvider, insertUpsert, sessionOutput, true, true, externalVars.keySet(), warningCollector);
InsertStatement rewrittenInsertUpsert = (InsertStatement) rewrittenResult.first;
@@ -3825,8 +3976,8 @@
boolean bActiveTxn = true;
metadataProvider.setMetadataTxnContext(mdTxnCtx);
try {
- final JobSpecification jobSpec = rewriteCompileQuery(hcc, metadataProvider, query, null, stmtParams,
- stmtRewriter, requestParameters);
+ final JobSpecification jobSpec =
+ rewriteCompileQuery(hcc, metadataProvider, query, null, stmtParams, requestParameters);
// update stats with count of compile-time warnings. needs to be adapted for multi-statement.
stats.updateTotalWarningsCount(warningCollector.getTotalWarningsCount());
afterCompile();
@@ -4377,18 +4528,14 @@
return i == 0;
}
- private Map<VarIdentifier, IAObject> createExternalVariables(Map<String, IAObject> stmtParams,
- IStatementRewriter stmtRewriter) {
+ private Map<VarIdentifier, IAObject> createExternalVariables(Map<String, IAObject> stmtParams) {
if (stmtParams == null || stmtParams.isEmpty()) {
return Collections.emptyMap();
}
+ IQueryRewriter queryRewriter = rewriterFactory.createQueryRewriter();
Map<VarIdentifier, IAObject> m = new HashMap<>();
for (Map.Entry<String, IAObject> me : stmtParams.entrySet()) {
- String paramName = me.getKey();
- String extVarName = stmtRewriter.toExternalVariableName(paramName);
- if (extVarName != null) {
- m.put(new VarIdentifier(extVarName), me.getValue());
- }
+ m.put(queryRewriter.toExternalVariableName(me.getKey()), me.getValue());
}
return m;
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/GlobalRecoveryManager.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/GlobalRecoveryManager.java
index e1c39a0..9438b16 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/GlobalRecoveryManager.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/GlobalRecoveryManager.java
@@ -43,6 +43,7 @@
import org.apache.asterix.metadata.entities.Dataverse;
import org.apache.asterix.metadata.entities.ExternalDatasetDetails;
import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.metadata.utils.DatasetUtil;
import org.apache.asterix.metadata.utils.ExternalIndexingOperations;
import org.apache.asterix.metadata.utils.MetadataConstants;
import org.apache.hyracks.api.application.ICCServiceContext;
@@ -137,7 +138,8 @@
for (Dataverse dataverse : dataverses) {
List<Dataset> dataverseDatasets =
MetadataManager.INSTANCE.getDataverseDatasets(mdTxnCtx, dataverse.getDataverseName());
- dataverseDatasets.stream().mapToInt(Dataset::getDatasetId).forEach(validDatasetIds::add);
+ dataverseDatasets.stream().filter(DatasetUtil::isNotView).mapToInt(Dataset::getDatasetId)
+ .forEach(validDatasetIds::add);
}
ICcApplicationContext ccAppCtx = (ICcApplicationContext) serviceCtx.getApplicationContext();
final List<String> ncs = new ArrayList<>(ccAppCtx.getClusterStateManager().getParticipantNodes());
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
index 9472da5..dcd52a0 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
@@ -253,7 +253,7 @@
clfrqs = new CompiledStatements.CompiledUpsertStatement(feedConn.getDataverseName(),
feedConn.getDatasetName(), feedConnQuery, stmtUpsert.getVarCounter(), null, null);
}
- return statementExecutor.rewriteCompileQuery(hcc, metadataProvider, feedConnQuery, clfrqs, null, null, null);
+ return statementExecutor.rewriteCompileQuery(hcc, metadataProvider, feedConnQuery, clfrqs, null, null);
}
private static JobSpecification combineIntakeCollectJobs(MetadataProvider metadataProvider, Feed feed,
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java
index fcdc25a..b0dc162 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java
@@ -354,7 +354,7 @@
// Drops dataset files of a given dataset.
private static void dropDatasetFiles(Dataset dataset, MetadataProvider metadataProvider,
IHyracksClientConnection hcc) throws Exception {
- if (dataset.getDatasetType() == DatasetType.EXTERNAL) {
+ if (dataset.getDatasetType() == DatasetType.EXTERNAL || dataset.getDatasetType() == DatasetType.VIEW) {
return;
}
List<JobSpecification> jobs = new ArrayList<>();
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
index 2039d53..8a87de7 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
@@ -19,6 +19,9 @@
package org.apache.asterix.test.sqlpp;
import static org.apache.hyracks.util.file.FileUtil.canonicalize;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -159,7 +162,17 @@
return mockDataverse;
}
});
- when(metadataProvider.findDataset(Mockito.<DataverseName> any(), Mockito.<String> any()))
+ when(metadataProvider.findDataset(any(DataverseName.class), anyString())).thenAnswer(new Answer<Dataset>() {
+ @Override
+ public Dataset answer(InvocationOnMock invocation) {
+ Object[] args = invocation.getArguments();
+ final Dataset mockDataset = mock(Dataset.class);
+ when(mockDataset.getDataverseName()).thenReturn((DataverseName) args[0]);
+ when(mockDataset.getDatasetName()).thenReturn((String) args[1]);
+ return mockDataset;
+ }
+ });
+ when(metadataProvider.findDataset(any(DataverseName.class), anyString(), anyBoolean()))
.thenAnswer(new Answer<Dataset>() {
@Override
public Dataset answer(InvocationOnMock invocation) {
@@ -170,7 +183,7 @@
return mockDataset;
}
});
- when(metadataProvider.lookupUserDefinedFunction(Mockito.<FunctionSignature> any()))
+ when(metadataProvider.lookupUserDefinedFunction(any(FunctionSignature.class)))
.thenAnswer(new Answer<Function>() {
@Override
public Function answer(InvocationOnMock invocation) {
@@ -189,7 +202,7 @@
if (st.getKind() == Statement.Kind.QUERY) {
Query query = (Query) st;
IQueryRewriter rewriter = sqlppRewriterFactory.createQueryRewriter();
- LangRewritingContext rwContext = new LangRewritingContext(metadataProvider, functions,
+ LangRewritingContext rwContext = new LangRewritingContext(metadataProvider, functions, null,
TestUtils.NOOP_WARNING_COLLECTOR, query.getVarCounter());
rewrite(rewriter, query, rwContext);
diff --git a/asterixdb/asterix-app/src/test/resources/metadata/queries/exception/exception_create_system_view/exception_create_system_view.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/metadata/queries/exception/exception_create_system_view/exception_create_system_view.1.ddl.sqlpp
new file mode 100644
index 0000000..5e69371
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/metadata/queries/exception/exception_create_system_view/exception_create_system_view.1.ddl.sqlpp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+create view Metadata.MyMetaView as
+ select count(*) from Metadata.`Dataset`;
diff --git a/asterixdb/asterix-app/src/test/resources/metadata/testsuite.xml b/asterixdb/asterix-app/src/test/resources/metadata/testsuite.xml
index a29dc48..dc6ae3d 100644
--- a/asterixdb/asterix-app/src/test/resources/metadata/testsuite.xml
+++ b/asterixdb/asterix-app/src/test/resources/metadata/testsuite.xml
@@ -363,6 +363,12 @@
</compilation-unit>
</test-case>
<test-case FilePath="exception">
+ <compilation-unit name="exception_create_system_view">
+ <output-dir compare="Text">none</output-dir>
+ <expected-error>ASX1079: Compilation error: Invalid operation - Cannot create a view belonging to the dataverse: Metadata (in line 20, at column 1)</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="exception">
<compilation-unit name="exception_declare_system_function">
<output-dir compare="Text">none</output-dir>
<expected-error>ASX1079: Compilation error: Invalid operation - Cannot declare a function belonging to the dataverse: Metadata (in line 22, at column 1)</expected-error>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.1.ddl.sqlpp
new file mode 100644
index 0000000..1b1210f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.1.ddl.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.
+ */
+
+/*
+ * Empty view name -> Error
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create view `` as
+ select r from range(0, 2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.2.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.2.ddl.sqlpp
new file mode 100644
index 0000000..a3a0172
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.2.ddl.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.
+ */
+
+/*
+ * View name starts with a space character -> Error
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create view ` a` as
+ select r from range(0, 2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.3.ddl.sqlpp
new file mode 100644
index 0000000..2774fe2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.3.ddl.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.
+ */
+
+/*
+ * Invalid dataverse name in CREATE VIEW -> Error
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create view ` invalid`.a as
+ select r from range(0, 2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.4.ddl.sqlpp
new file mode 100644
index 0000000..d38df4c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.4.ddl.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.
+ */
+
+/*
+ * Invalid dataverse name in CREATE VIEW -> Error
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create view `a/b`.a as
+ select r from range(0, 2) r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.5.ddl.sqlpp
new file mode 100644
index 0000000..6acc680
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/ddl/invalid-view-name/invalid-view-name.5.ddl.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+/*
+ * Invalid dataverse name in DROP VIEW -> Error
+ */
+
+drop dataverse c.d if exists;
+create dataverse c.d;
+
+use c.d;
+
+create view e as
+ select r from range(0, 2) r;
+
+drop view `c/d`.e;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.1.ddl.sqlpp
new file mode 100644
index 0000000..f28ae6b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.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: views in a dataverse with a multipart name
+ */
+
+drop dataverse x.y if exists;
+create dataverse x.y;
+
+drop dataverse x.z if exists;
+create dataverse x.z;
+
+create view x.z.vz as
+ select r from range(0,2) r;
+
+create view x.y.vy as
+ select vz.* from x.z.vz;
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.2.query.sqlpp
new file mode 100644
index 0000000..6293c28
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_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.
+ */
+/*
+ * Description: views in a dataverse with a multipart name
+ */
+
+select value r
+from x.y.vy r
+order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.3.query.sqlpp
new file mode 100644
index 0000000..de77ed0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/view_1/view_1.3.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description: views in a dataverse with a multipart name
+ */
+
+select DataverseName, DatasetName,
+ ViewDetails.Dependencies Dependencies
+from Metadata.`Dataset`
+where DataverseName like "x%" and DatasetType = "VIEW"
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.1.ddl.sqlpp
new file mode 100644
index 0000000..66965a1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.1.ddl.sqlpp
@@ -0,0 +1,68 @@
+/*
+ * 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 test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+use test2;
+
+--- test2
+
+create synonym DataverseSyn2 for Metadata.`Dataverse`;
+
+create function f2() {
+ select count(*) as f2 from DataverseSyn2
+ where DataverseName like "t%"
+};
+
+create view v2 as select sum(r) as v2 from range(1,2) r;
+
+--- test1
+
+create synonym test1.DataverseSyn1 for Metadata.`Dataverse`;
+
+create view test1.v1 as select sum(r) as v1 from range(1,3) r;
+
+create function test1.f1() {
+ select count(*) as f1 from DataverseSyn1
+ where DataverseName like "t%"
+};
+
+create view test1.vA as
+ select v1.*, v2.*, f1.*, f2.*, s1.*, s2.*, d1.*
+ from
+ v1 v1,
+ test2.v2 v2,
+ f1() f1,
+ test2.f2() f2,
+ (
+ select count(*) as s1 from DataverseSyn1
+ where DataverseName like "te%"
+ ) s1,
+ (
+ select count(*) as s2 from test2.DataverseSyn2
+ where DataverseName like "tes%"
+ ) s2,
+ (
+ select count(*) as d1 from Metadata.`Dataverse`
+ where DataverseName like "test%"
+ ) d1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.10.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.10.ddl.sqlpp
new file mode 100644
index 0000000..073842f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.10.ddl.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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 "or replace"
+
+create or replace view test1.vA as
+ select r from range(3,4) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.11.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.11.query.sqlpp
new file mode 100644
index 0000000..443d9eb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.11.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 test1;
+
+select value vA from vA order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.12.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.12.query.sqlpp
new file mode 100644
index 0000000..80aa2dc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.12.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.
+ */
+
+select DataverseName, DatasetName,
+ DatatypeDataverseName, DatatypeName, ViewDetails
+from Metadata.`Dataset`
+where DataverseName like "test%" and DatasetType = "VIEW" and DatasetName = "vA"
+order by DataverseName, DatasetName;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.2.query.sqlpp
new file mode 100644
index 0000000..d7b182f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-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 test1;
+
+select value vA from vA;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.3.query.sqlpp
new file mode 100644
index 0000000..2cf093f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-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.
+ */
+
+select DataverseName, DatasetName,
+ DatatypeDataverseName, DatatypeName, ViewDetails
+from Metadata.`Dataset`
+where DataverseName like "test%" and DatasetType = "VIEW"
+order by DataverseName, DatasetName;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.4.ddl.sqlpp
new file mode 100644
index 0000000..237100e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.4.ddl.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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 "if not exists" when the view already exists
+
+create view test1.vA if not exists as
+ select r from range(1,2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.5.query.sqlpp
new file mode 100644
index 0000000..636f5da
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.5.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.
+ */
+
+--- same result as before
+
+use test1;
+
+select value vA from vA;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.6.query.sqlpp
new file mode 100644
index 0000000..a204c97
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.6.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+--- same result as before
+
+select DataverseName, DatasetName,
+ DatatypeDataverseName, DatatypeName, ViewDetails
+from Metadata.`Dataset`
+where DataverseName like "test%" and DatasetType = "VIEW" and DatasetName = "vA"
+order by DataverseName, DatasetName;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.7.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.7.ddl.sqlpp
new file mode 100644
index 0000000..8d6169f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.7.ddl.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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 "if not exists" when the view does not yet exist
+
+create view test1.vB if not exists as
+ select r from range(1,2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.8.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.8.query.sqlpp
new file mode 100644
index 0000000..bb1f529
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.8.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 test1;
+
+select value vB from vB order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.9.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.9.query.sqlpp
new file mode 100644
index 0000000..84038a9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-1/create-view-1.9.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.
+ */
+
+select DataverseName, DatasetName,
+ DatatypeDataverseName, DatatypeName, ViewDetails
+from Metadata.`Dataset`
+where DataverseName like "test%" and DatasetType = "VIEW" and DatasetName = "vB"
+order by DataverseName, DatasetName;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.1.ddl.sqlpp
new file mode 100644
index 0000000..f8224ef
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.1.ddl.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.
+ */
+
+--- Negative: unknown dataverse
+
+drop dataverse test if exists;
+
+create view test.v1 as select r from range(1,2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.10.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.10.ddl.sqlpp
new file mode 100644
index 0000000..9a8fa71
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.10.ddl.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.
+ */
+
+--- Negative: recursive definitions (view/function)
+
+drop dataverse test if exists;
+create dataverse test;
+
+create view test.v1 as
+ select * from range(1,2) r;
+
+create function test.f2() {
+ select * from v1 r
+};
+
+create or replace view test.v1 as
+ select * from f2() r;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.11.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.11.ddl.sqlpp
new file mode 100644
index 0000000..5aab3ac
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.11.ddl.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+--- Negative: recursive definitions (function/view)
+
+drop dataverse test if exists;
+create dataverse test;
+
+create function test.f1() {
+ select * from range(1,2) r
+};
+
+create view test.v2 as
+ select * from f1() r
+;
+
+create or replace function test.f1() {
+ select * from v2 r
+};
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.2.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.2.ddl.sqlpp
new file mode 100644
index 0000000..0340d2c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.2.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.
+ */
+
+--- Negative: invalid view definition (syntax)
+
+drop dataverse test if exists;
+create dataverse test;
+
+create view test.v1 as select * from range(1,2) r order by;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.3.ddl.sqlpp
new file mode 100644
index 0000000..93cde91
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.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.
+ */
+
+--- Negative: invalid view definition (unknown used function)
+
+drop dataverse test if exists;
+create dataverse test;
+
+create view test.v1 as select * from undefined_range(1,2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.4.ddl.sqlpp
new file mode 100644
index 0000000..6969d78
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.4.ddl.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+--- Negative: create view fails because view with this name already exists
+
+drop dataverse test if exists;
+create dataverse test;
+
+create view test.v1 as select * from range(1,2) r;
+create view test.v1 as select * from range(3,4) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.5.ddl.sqlpp
new file mode 100644
index 0000000..da541d1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.5.ddl.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.
+ */
+
+--- Negative: create view fails because dataset with this name already exists
+
+drop dataverse test if exists;
+create dataverse test;
+
+create dataset test.ds1(
+ c_custkey integer not unknown,
+ c_name string not unknown
+) primary key c_custkey;
+
+create view test.ds1 as select * from range(1,2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.6.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.6.ddl.sqlpp
new file mode 100644
index 0000000..f6aefe9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.6.ddl.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.
+ */
+
+--- Negative: create or replace view fails because dataset with this name already exists
+
+drop dataverse test if exists;
+create dataverse test;
+
+create dataset test.ds2(
+ c_custkey integer not unknown,
+ c_name string not unknown
+) primary key c_custkey;
+
+create or replace view test.ds2 as select * from range(1,2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.7.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.7.ddl.sqlpp
new file mode 100644
index 0000000..56e24e7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.7.ddl.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.
+ */
+
+--- Negative: create dataset fails because view with this name already exists
+
+drop dataverse test if exists;
+create dataverse test;
+
+create view test.ds1 as select * from range(1,2) r;
+
+create dataset test.ds1(
+ c_custkey integer not unknown,
+ c_name string not unknown
+) primary key c_custkey;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.8.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.8.ddl.sqlpp
new file mode 100644
index 0000000..97a7709
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.8.ddl.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+--- Negative: "or replace" with "if not exists"
+
+drop dataverse test if exists;
+create dataverse test;
+
+create or replace view test.v1 if not exists as
+ select * from range(1,2) r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.9.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.9.ddl.sqlpp
new file mode 100644
index 0000000..a9ef305
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/create-view-2-negative/create-view-2-negative.9.ddl.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+--- Negative: recursive definitions (view/view)
+
+drop dataverse test if exists;
+create dataverse test;
+
+create view test.v1 as
+ select * from range(1,2) r;
+
+create view test.v2 as
+ select * from v1 r;
+
+create or replace view test.v1 as
+ select * from v2 r;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-1/drop-dataverse-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-1/drop-dataverse-1.1.ddl.sqlpp
new file mode 100644
index 0000000..27ae6ab
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-1/drop-dataverse-1.1.ddl.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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 drop dataverse with views
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+create view test1.v1 as
+ select r from range(0,2) r;
+
+create view test1.v2 as
+ select v1.* from v1;
+
+drop dataverse test1;
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.1.ddl.sqlpp
new file mode 100644
index 0000000..f3f0334
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.1.ddl.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.
+ */
+
+--- Test that DROP DATAVERSE fails due to cross-dataverse dependencies
+
+--- View depends on view
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create view test2.v2 as select r from range(1,2) r;
+
+create view test1.v1 as select v2.* from test2.v2;
+
+drop dataverse test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.2.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.2.ddl.sqlpp
new file mode 100644
index 0000000..d8f90bb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.2.ddl.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.
+ */
+
+--- Test that DROP DATAVERSE fails due to cross-dataverse dependencies
+
+--- Function depends on view
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create view test2.v2 as select r from range(1,2) r;
+
+create function test1.f1() { select v2.* from test2.v2 };
+
+drop dataverse test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.3.ddl.sqlpp
new file mode 100644
index 0000000..5089a6a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.3.ddl.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.
+ */
+
+--- Test that DROP DATAVERSE fails due to cross-dataverse dependencies
+
+--- View depends on dataset
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create dataset test2.ds2(c1 bigint not unknown, c2 bigint) primary key c1;
+
+create view test1.v1 as select ds2.* from test2.ds2;
+
+drop dataverse test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.4.ddl.sqlpp
new file mode 100644
index 0000000..8c28081
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.4.ddl.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.
+ */
+
+--- Test that DROP DATAVERSE fails due to cross-dataverse dependencies
+
+--- View depends on function
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create function test2.f2() { select r from range(1,2) r };
+
+create view test1.v1 as select f2.* from test2.f2() f2;
+
+drop dataverse test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.5.ddl.sqlpp
new file mode 100644
index 0000000..cf055ae
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-dataverse-2-negative/drop-dataverse-2-negative.5.ddl.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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 that DROP DATAVERSE fails due to cross-dataverse dependencies
+
+--- View depends on synonym
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create dataset test2.ds2(c1 bigint not unknown, c2 bigint) primary key c1;
+
+create synonym test2.s3 for ds2;
+
+create view test1.v1 as select s3.* from test2.s3;
+
+drop dataverse test2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-1/drop-view-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-1/drop-view-1.1.ddl.sqlpp
new file mode 100644
index 0000000..16c1d6d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-1/drop-view-1.1.ddl.sqlpp
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+drop view test.v1 if exists;
+
+create view test.v2 as
+ select r from range(1,2) r;
+
+drop view test.v2 if exists;
+
+create view test.v3 as
+ select r from range(3,4) r;
+
+drop view test.v3;
+
+create view test.v4 as
+ select r from range(3,4) r;
+
+create synonym test.s4 for v4;
+
+-- ok to drop a view if a synonym depends on it
+
+drop view test.v4;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-1/drop-view-1.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-1/drop-view-1.2.query.sqlpp
new file mode 100644
index 0000000..4c8483e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-1/drop-view-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.
+ */
+
+select count(*) cnt
+from Metadata.`Dataset`
+where DataverseName = "test" and DatasetType = "VIEW";
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.1.ddl.sqlpp
new file mode 100644
index 0000000..c92c33a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.1.ddl.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.
+ */
+
+--- Negative: unknown dataverse
+
+drop dataverse test if exists;
+
+drop view test.v1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.10.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.10.query.sqlpp
new file mode 100644
index 0000000..7aa6517
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.10.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.
+ */
+
+-- check that the function was not dropped
+
+select value f2 from test2.f2() f2 order by f2.r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.11.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.11.ddl.sqlpp
new file mode 100644
index 0000000..009dd83
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.11.ddl.sqlpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+--- Negative: drop synonym fails if a view depends on it
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create dataset test2.ds2(
+ c_custkey integer not unknown,
+ c_name string not unknown
+) primary key c_custkey;
+
+create synonym test2.s2 for test2.ds2;
+
+create view test1.v1 as
+ select * from test2.s2;
+
+drop synonym test2.s2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.12.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.12.query.sqlpp
new file mode 100644
index 0000000..4a425b4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.12.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.
+ */
+
+-- check that the synonym was not dropped
+
+select value count(*) from test2.s2;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.13.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.13.ddl.sqlpp
new file mode 100644
index 0000000..27acbde
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.13.ddl.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.
+ */
+
+--- Negative: drop view fails if a view depends on it
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create view test2.v2 as
+ select * from range(1,2) r;
+
+create view test1.v1 as
+ select * from test2.v2;
+
+drop view test2.v2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.14.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.14.query.sqlpp
new file mode 100644
index 0000000..f009fcf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.14.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.
+ */
+
+-- check that the view was not dropped
+
+select value v2 from test2.v2 v2 order by v2.r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.15.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.15.ddl.sqlpp
new file mode 100644
index 0000000..c759a13
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.15.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.
+ */
+
+--- Negative: drop view fails if a function depends on it
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create view test2.v2 as
+ select * from range(1,2) r;
+
+create function test1.f1() {
+ select * from test2.v2
+};
+
+drop view test2.v2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.16.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.16.query.sqlpp
new file mode 100644
index 0000000..f009fcf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.16.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.
+ */
+
+-- check that the view was not dropped
+
+select value v2 from test2.v2 v2 order by v2.r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.2.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.2.ddl.sqlpp
new file mode 100644
index 0000000..4480882
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.2.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.
+ */
+
+--- Negative: unknown view
+
+drop dataverse test if exists;
+create dataverse test;
+
+drop view test.v1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.3.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.3.ddl.sqlpp
new file mode 100644
index 0000000..2034c22
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.3.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.
+ */
+
+--- Negative: drop dataset fails if target is a view
+
+drop dataverse test if exists;
+create dataverse test;
+
+create view test.v1 as select r from range(1,2) r;
+
+drop dataset test.v1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.4.query.sqlpp
new file mode 100644
index 0000000..1275dbe
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.4.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.
+ */
+
+-- check that the view was not dropped
+
+select value r from test.v1 r order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.5.ddl.sqlpp
new file mode 100644
index 0000000..3a1fd33
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.5.ddl.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.
+ */
+
+--- Negative: drop view fails if target is a dataset
+
+drop dataverse test if exists;
+create dataverse test;
+
+create dataset test.ds1(
+ c_custkey integer not unknown,
+ c_name string not unknown
+) primary key c_custkey;
+
+drop view test.ds1;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.6.query.sqlpp
new file mode 100644
index 0000000..12971b1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.6.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.
+ */
+
+-- check that the dataset was not dropped
+
+select value count(*) from test.ds1;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.7.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.7.ddl.sqlpp
new file mode 100644
index 0000000..92d2270
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.7.ddl.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+--- Negative: drop dataset fails if a view depends on it
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create dataset test2.ds2(
+ c_custkey integer not unknown,
+ c_name string not unknown
+) primary key c_custkey;
+
+create view test1.v1 as
+ select * from test2.ds2;
+
+drop dataset test2.ds2;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.8.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.8.query.sqlpp
new file mode 100644
index 0000000..dd85dbe
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.8.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.
+ */
+
+-- check that the dataset was not dropped
+
+select value count(*) from test2.ds2;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.9.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.9.ddl.sqlpp
new file mode 100644
index 0000000..83d4fab
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/drop-view-2-negative/drop-view-2-negative.9.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.
+ */
+
+--- Negative: drop function fails if a view depends on it
+
+drop dataverse test1 if exists;
+create dataverse test1;
+
+drop dataverse test2 if exists;
+create dataverse test2;
+
+create function test2.f2() {
+ select * from range(1,2) r
+};
+
+create view test1.v1 as
+ select * from test2.f2() f2;
+
+drop function test2.f2();
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.1.ddl.sqlpp
new file mode 100644
index 0000000..e5a22ec
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.1.ddl.sqlpp
@@ -0,0 +1,44 @@
+/*
+ * 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 test1 if exists;
+create dataverse test1;
+
+use test1;
+
+create dataset ds1(
+ c1 bigint not unknown,
+ c2 bigint
+) primary key c1;
+
+create synonym s2 for ds1;
+
+create view v3 as
+ select c1, c2 from s2;
+
+create synonym s4 for v3;
+
+create function f5() {
+ select c1, c2 from s4
+};
+
+create view v6 as
+ select c1, c2 from f5() f5;
+
+create synonym s7 for v6;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.2.update.sqlpp
new file mode 100644
index 0000000..260b64f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.2.update.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 test1;
+
+insert into ds1 select r c1, 9 - r c2 from range(0, 9) r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.3.query.sqlpp
new file mode 100644
index 0000000..6c92c4a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.3.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 test1;
+
+select s7.* from s7 order by c1;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.4.query.sqlpp
new file mode 100644
index 0000000..57b5010
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.4.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "VIEW" Kind, DatasetName Name,
+ ViewDetails.`Definition` `Definition`,
+ ViewDetails.Dependencies Dependencies
+from Metadata.`Dataset`
+where DataverseName like "test1%" and DatasetType = "VIEW"
+
+union all
+
+select "FUNCTION" Kind, Name, `Definition`, Dependencies
+from Metadata.`Function`
+where DataverseName like "test1%"
+
+order by Name;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.5.ddl.sqlpp
new file mode 100644
index 0000000..97f9ec4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.5.ddl.sqlpp
@@ -0,0 +1,74 @@
+/*
+ * 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 test2 if exists;
+create dataverse test2;
+
+use test2;
+
+create dataset ds1(
+ c1 bigint not unknown,
+ c2 bigint
+) primary key c1;
+
+create dataset ds2(
+ c1 bigint not unknown,
+ c2 bigint
+) primary key c1;
+
+create view v3 as
+ select c1, c2 from ds1
+ union all
+ select c1, c2 from ds2;
+
+create view v4 as
+ select c1, c2 from ds1
+ union all
+ select c1, c2 from ds2;
+
+create function f5() {
+ select c1, c2 from v3
+};
+
+create function f6() {
+ select c1, c2 from v4
+};
+
+create synonym s7 for ds1;
+
+create synonym s8 for ds2;
+
+create view v9 as
+ select c1, c2 from ds1
+ union all
+ select c1, c2 from ds2
+ union all
+ select c1, c2 from v3
+ union all
+ select c1, c2 from v4
+ union all
+ select c1, c2 from f5() f5
+ union all
+ select c1, c2 from f6() f6
+ union all
+ select c1, c2 from s7
+ union all
+ select c1, c2 from s8;
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.6.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.6.update.sqlpp
new file mode 100644
index 0000000..902c718
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.6.update.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 test2;
+
+insert into ds1 select r c1, 2 - r c2 from range(0, 2) r;
+
+insert into ds2 select r c1, 2 - r c2 from range(0, 2) r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.7.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.7.query.sqlpp
new file mode 100644
index 0000000..762f234
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.7.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 test2;
+
+select count(*) c,
+ array_sort(array_agg(distinct c1)) c1,
+ array_sort(array_agg(distinct c2)) c2
+from v9;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.8.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.8.query.sqlpp
new file mode 100644
index 0000000..d41ee20
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/view/view-1/view-1.8.query.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.
+ */
+
+select "VIEW" Kind, DatasetName Name,
+ ViewDetails.Dependencies Dependencies
+from Metadata.`Dataset`
+where DataverseName like "test2%" and DatasetType = "VIEW"
+
+union all
+
+select "FUNCTION" Kind, Name, Dependencies
+from Metadata.`Function`
+where DataverseName like "test2%"
+
+order by Name;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/multipart-dataverse/view_1/view_1.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/multipart-dataverse/view_1/view_1.2.adm
new file mode 100644
index 0000000..00cf01e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/multipart-dataverse/view_1/view_1.2.adm
@@ -0,0 +1,3 @@
+{ "r": 0 }
+{ "r": 1 }
+{ "r": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/multipart-dataverse/view_1/view_1.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/multipart-dataverse/view_1/view_1.3.adm
new file mode 100644
index 0000000..c746a5a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/multipart-dataverse/view_1/view_1.3.adm
@@ -0,0 +1,2 @@
+{ "DataverseName": "x/y", "DatasetName": "vy", "Dependencies": [ [ [ "x/z", "vz" ] ], [ ], [ ] ] }
+{ "DataverseName": "x/z", "DatasetName": "vz", "Dependencies": [ [ ], [ ], [ ] ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.11.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.11.adm
new file mode 100644
index 0000000..8d802cd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.11.adm
@@ -0,0 +1,2 @@
+{ "r": 3 }
+{ "r": 4 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.12.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.12.adm
new file mode 100644
index 0000000..42561b4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.12.adm
@@ -0,0 +1 @@
+{ "DataverseName": "test1", "DatasetName": "vA", "DatatypeDataverseName": "Metadata", "DatatypeName": "AnyObject", "ViewDetails": { "Definition": "select r from range(3,4) r", "Dependencies": [ [ ], [ ], [ ] ] } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.2.adm
new file mode 100644
index 0000000..f9bc681
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.2.adm
@@ -0,0 +1 @@
+{ "d1": 2, "s2": 2, "s1": 2, "f2": 2, "f1": 2, "v2": 3, "v1": 6 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.3.adm
new file mode 100644
index 0000000..6ceac5d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.3.adm
@@ -0,0 +1,3 @@
+{ "DataverseName": "test1", "DatasetName": "v1", "DatatypeDataverseName": "Metadata", "DatatypeName": "AnyObject", "ViewDetails": { "Definition": "select sum(r) as v1 from range(1,3) r", "Dependencies": [ [ ], [ ], [ ] ] } }
+{ "DataverseName": "test1", "DatasetName": "vA", "DatatypeDataverseName": "Metadata", "DatatypeName": "AnyObject", "ViewDetails": { "Definition": "select v1.*, v2.*, f1.*, f2.*, s1.*, s2.*, d1.*\n from\n v1 v1,\n test2.v2 v2,\n f1() f1,\n test2.f2() f2,\n (\n select count(*) as s1 from DataverseSyn1\n where DataverseName like \"te%\"\n ) s1,\n (\n select count(*) as s2 from test2.DataverseSyn2\n where DataverseName like \"tes%\"\n ) s2,\n (\n select count(*) as d1 from Metadata.`Dataverse`\n where DataverseName like \"test%\"\n ) d1", "Dependencies": [ [ [ "test1", "v1" ], [ "test2", "v2" ], [ "Metadata", "Dataverse" ] ], [ [ "test1", "f1", "0" ], [ "test2", "f2", "0" ] ], [ ], [ [ "test1", "DataverseSyn1" ], [ "test2", "DataverseSyn2" ] ] ] } }
+{ "DataverseName": "test2", "DatasetName": "v2", "DatatypeDataverseName": "Metadata", "DatatypeName": "AnyObject", "ViewDetails": { "Definition": "select sum(r) as v2 from range(1,2) r", "Dependencies": [ [ ], [ ], [ ] ] } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.5.adm
new file mode 100644
index 0000000..f9bc681
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.5.adm
@@ -0,0 +1 @@
+{ "d1": 2, "s2": 2, "s1": 2, "f2": 2, "f1": 2, "v2": 3, "v1": 6 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.6.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.6.adm
new file mode 100644
index 0000000..ccb58cd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.6.adm
@@ -0,0 +1 @@
+{ "DataverseName": "test1", "DatasetName": "vA", "DatatypeDataverseName": "Metadata", "DatatypeName": "AnyObject", "ViewDetails": { "Definition": "select v1.*, v2.*, f1.*, f2.*, s1.*, s2.*, d1.*\n from\n v1 v1,\n test2.v2 v2,\n f1() f1,\n test2.f2() f2,\n (\n select count(*) as s1 from DataverseSyn1\n where DataverseName like \"te%\"\n ) s1,\n (\n select count(*) as s2 from test2.DataverseSyn2\n where DataverseName like \"tes%\"\n ) s2,\n (\n select count(*) as d1 from Metadata.`Dataverse`\n where DataverseName like \"test%\"\n ) d1", "Dependencies": [ [ [ "test1", "v1" ], [ "test2", "v2" ], [ "Metadata", "Dataverse" ] ], [ [ "test1", "f1", "0" ], [ "test2", "f2", "0" ] ], [ ], [ [ "test1", "DataverseSyn1" ], [ "test2", "DataverseSyn2" ] ] ] } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.8.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.8.adm
new file mode 100644
index 0000000..7b4ad0c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.8.adm
@@ -0,0 +1,2 @@
+{ "r": 1 }
+{ "r": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.9.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.9.adm
new file mode 100644
index 0000000..991315f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/create-view-1/create-view-1.9.adm
@@ -0,0 +1 @@
+{ "DataverseName": "test1", "DatasetName": "vB", "DatatypeDataverseName": "Metadata", "DatatypeName": "AnyObject", "ViewDetails": { "Definition": "select r from range(1,2) r", "Dependencies": [ [ ], [ ], [ ] ] } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-1/drop-view-1.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-1/drop-view-1.2.adm
new file mode 100644
index 0000000..bacb60c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-1/drop-view-1.2.adm
@@ -0,0 +1 @@
+{ "cnt": 0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.10.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.10.adm
new file mode 100644
index 0000000..7b4ad0c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.10.adm
@@ -0,0 +1,2 @@
+{ "r": 1 }
+{ "r": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.12.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.12.adm
new file mode 100644
index 0000000..c227083
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.12.adm
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.14.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.14.adm
new file mode 100644
index 0000000..7b4ad0c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.14.adm
@@ -0,0 +1,2 @@
+{ "r": 1 }
+{ "r": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.16.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.16.adm
new file mode 100644
index 0000000..7b4ad0c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.16.adm
@@ -0,0 +1,2 @@
+{ "r": 1 }
+{ "r": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.4.adm
new file mode 100644
index 0000000..7b4ad0c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.4.adm
@@ -0,0 +1,2 @@
+{ "r": 1 }
+{ "r": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.6.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.6.adm
new file mode 100644
index 0000000..c227083
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.6.adm
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.8.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.8.adm
new file mode 100644
index 0000000..c227083
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/drop-view-2-negative/drop-view-2-negative.8.adm
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.3.adm
new file mode 100644
index 0000000..a42eb92
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.3.adm
@@ -0,0 +1,10 @@
+{ "c1": 0, "c2": 9 }
+{ "c1": 1, "c2": 8 }
+{ "c1": 2, "c2": 7 }
+{ "c1": 3, "c2": 6 }
+{ "c1": 4, "c2": 5 }
+{ "c1": 5, "c2": 4 }
+{ "c1": 6, "c2": 3 }
+{ "c1": 7, "c2": 2 }
+{ "c1": 8, "c2": 1 }
+{ "c1": 9, "c2": 0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.4.adm
new file mode 100644
index 0000000..0c0c564
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.4.adm
@@ -0,0 +1,3 @@
+{ "Kind": "FUNCTION", "Name": "f5", "Definition": "select c1, c2 from s4", "Dependencies": [ [ ], [ ], [ ], [ [ "test1", "s4" ] ] ] }
+{ "Kind": "VIEW", "Name": "v3", "Definition": "select c1, c2 from s2", "Dependencies": [ [ ], [ ], [ ], [ [ "test1", "s2" ] ] ] }
+{ "Kind": "VIEW", "Name": "v6", "Definition": "select c1, c2 from f5() f5", "Dependencies": [ [ ], [ [ "test1", "f5", "0" ] ], [ ] ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.7.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.7.adm
new file mode 100644
index 0000000..554bf72
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.7.adm
@@ -0,0 +1 @@
+{ "c": 36, "c1": [ 0, 1, 2 ], "c2": [ 0, 1, 2 ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.8.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.8.adm
new file mode 100644
index 0000000..98d2942
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/view/view-1/view-1.8.adm
@@ -0,0 +1,5 @@
+{ "Kind": "FUNCTION", "Name": "f5", "Dependencies": [ [ [ "test2", "v3" ] ], [ ], [ ] ] }
+{ "Kind": "FUNCTION", "Name": "f6", "Dependencies": [ [ [ "test2", "v4" ] ], [ ], [ ] ] }
+{ "Kind": "VIEW", "Name": "v3", "Dependencies": [ [ [ "test2", "ds1" ], [ "test2", "ds2" ] ], [ ], [ ] ] }
+{ "Kind": "VIEW", "Name": "v4", "Dependencies": [ [ [ "test2", "ds1" ], [ "test2", "ds2" ] ], [ ], [ ] ] }
+{ "Kind": "VIEW", "Name": "v9", "Dependencies": [ [ [ "test2", "ds1" ], [ "test2", "ds2" ], [ "test2", "v3" ], [ "test2", "v4" ] ], [ [ "test2", "f5", "0" ], [ "test2", "f6", "0" ] ], [ ], [ [ "test2", "s7" ], [ "test2", "s8" ] ] ] }
\ No newline at end of file
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 6c67216..85fe2c5 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
@@ -27,7 +27,7 @@
<compilation-unit name="bad-ext-function-ddl-1">
<output-dir compare="Text">none</output-dir>
<expected-error>ASX1079: Compilation error: Variable number of parameters is not supported for external functions</expected-error>
- <expected-error>ASX1001: Syntax error: Unexpected IF NOT EXISTS (in line 25, at column 1)</expected-error>
+ <expected-error>ASX1001: Syntax error: Unexpected IF NOT EXISTS (in line 25, at column 57)</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 02b5721..9a92a6c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -4239,6 +4239,16 @@
</compilation-unit>
</test-case>
<test-case FilePath="ddl">
+ <compilation-unit name="invalid-view-name">
+ <output-dir compare="Text">none</output-dir>
+ <expected-error>ASX1115: Invalid name for a database object: "" (in line 29, at column 1)</expected-error>
+ <expected-error>ASX1115: Invalid name for a database object: " a" (in line 29, at column 1)</expected-error>
+ <expected-error>ASX1115: Invalid name for a database object: " invalid" (in line 29, at column 1)</expected-error>
+ <expected-error>ASX1115: Invalid name for a database object: "a/b" (in line 29, at column 13)</expected-error>
+ <expected-error>ASX1115: Invalid name for a database object: "c/d" (in line 32, at column 11)</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="ddl">
<compilation-unit name="dataset-and-index-same-dataverse">
<output-dir compare="Text">dataset-and-index-same-dataverse</output-dir>
</compilation-unit>
@@ -12602,7 +12612,7 @@
<expected-error>ASX1001: Syntax error: Unexpected type declaration for parameter a in function myfn001</expected-error>
<expected-error>ASX1001: Syntax error: Unexpected return type declaration for function myfn002</expected-error>
<expected-error>ASX1001: Syntax error: Unexpected return type declaration for function myfn003</expected-error>
- <expected-error>ASX1001: Syntax error: Unexpected IF NOT EXISTS (in line 29, at column 1)</expected-error>
+ <expected-error>ASX1001: Syntax error: Unexpected IF NOT EXISTS (in line 29, at column 45)</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
@@ -12628,8 +12638,8 @@
<test-case FilePath="user-defined-functions">
<compilation-unit name="drop-dependency-2">
<output-dir compare="Text">drop-dependency-2</output-dir>
- <expected-error>ASX1147: Cannot drop dataverse: dataset C.TweetMessages being used by function B.f2(2)</expected-error>
- <expected-error>ASX1147: Cannot drop dataverse: dataset C.TweetMessages being used by function B.f3(...)</expected-error>
+ <expected-error>ASX1147: Cannot drop dataverse: dataset (or view) C.TweetMessages being used by function B.f2(2)</expected-error>
+ <expected-error>ASX1147: Cannot drop dataverse: dataset (or view) C.TweetMessages being used by function B.f3(...)</expected-error>
<source-location>false</source-location>
</compilation-unit>
</test-case>
@@ -12912,14 +12922,14 @@
<test-case FilePath="user-defined-functions">
<compilation-unit name="udf37_recursion">
<output-dir compare="Text">none</output-dir>
- <expected-error>ASX1149: Illegal function recursion (in line 24, at column 1)</expected-error>
- <expected-error>ASX1149: Illegal function recursion (in line 25, at column 1)</expected-error>
- <expected-error>ASX1149: Illegal function recursion (in line 26, at column 1)</expected-error>
- <expected-error>ASX1149: Illegal function recursion (in line 27, at column 1)</expected-error>
- <expected-error>ASX1149: Illegal function recursion (in line 28, at column 1)</expected-error>
- <expected-error>ASX1149: Illegal function recursion (in line 29, at column 1)</expected-error>
- <expected-error>ASX1149: Illegal function recursion (in line 30, at column 1)</expected-error>
- <expected-error>ASX1149: Illegal function recursion (in line 31, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 24, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 25, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 26, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 27, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 28, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 29, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 30, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 31, at column 1)</expected-error>
</compilation-unit>
</test-case>
<test-case FilePath="user-defined-functions">
@@ -12965,6 +12975,70 @@
</compilation-unit>
</test-case>
</test-group>
+ <test-group name="view">
+ <test-case FilePath="view">
+ <compilation-unit name="create-view-1">
+ <output-dir compare="Text">create-view-1</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="view">
+ <compilation-unit name="create-view-2-negative">
+ <output-dir compare="Text">none</output-dir>
+ <expected-error>ASX1063: Cannot find dataverse with name test (in line 24, at column 1)</expected-error>
+ <expected-error><![CDATA[ASX1001: Syntax error: In line 25 >>create view test.v1 as select * from range(1,2) r order by;<< Encountered ";" at column 59]]></expected-error>
+ <expected-error>ASX1081: Cannot find function with signature test.undefined_range(2) (in line 25, at column 38)</expected-error>
+ <expected-error>ASX1160: A view with this name test.v1 already exists (in line 26, at column 1)</expected-error>
+ <expected-error>ASX1072: A dataset with name ds1 already exists in dataverse test (in line 30, at column 1)</expected-error>
+ <expected-error>ASX1072: A dataset with name ds2 already exists in dataverse test (in line 30, at column 1)</expected-error>
+ <expected-error>ASX1160: A view with this name test.ds1 already exists (in line 27, at column 1)</expected-error>
+ <expected-error><![CDATA[ASX1001: Syntax error: Unexpected IF NOT EXISTS (in line 25, at column 39)]]></expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 31, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 32, at column 1)</expected-error>
+ <expected-error>ASX1149: Illegal function or view recursion (in line 33, at column 1)</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="view">
+ <compilation-unit name="drop-dataverse-1">
+ <output-dir compare="Text">none</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="view">
+ <compilation-unit name="drop-dataverse-2-negative">
+ <output-dir compare="Text">none</output-dir>
+ <expected-error>ASX1147: Cannot drop dataverse: dataset (or view) test2.v2 being used by view test1.v1</expected-error>
+ <expected-error>ASX1147: Cannot drop dataverse: dataset (or view) test2.v2 being used by function test1.f1()</expected-error>
+ <expected-error>ASX1147: Cannot drop dataverse: dataset (or view) test2.ds2 being used by view test1.v1</expected-error>
+ <expected-error>ASX1147: Cannot drop dataverse: function test2.f2() being used by view test1.v1</expected-error>
+ <expected-error>ASX1147: Cannot drop dataverse: synonym test2.s3 being used by view test1.v1</expected-error>
+ <source-location>false</source-location>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="view">
+ <compilation-unit name="drop-view-1">
+ <output-dir compare="Text">drop-view-1</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="view">
+ <compilation-unit name="drop-view-2-negative">
+ <output-dir compare="Text">drop-view-2-negative</output-dir>
+ <expected-error>ASX1063: Cannot find dataverse with name test (in line 24, at column 1)</expected-error>
+ <expected-error>ASX1159: Cannot find view with name test.v1 (in line 25, at column 1)</expected-error>
+ <expected-error>ASX1050: Cannot find dataset with name v1 in dataverse test (in line 27, at column 1)</expected-error>
+ <expected-error>ASX1159: Cannot find view with name test.ds1 (in line 30, at column 1)</expected-error>
+ <expected-error>ASX1148: Cannot drop dataset test2.ds2 being used by view test1.v1</expected-error>
+ <expected-error>ASX1148: Cannot drop function test2.f2() being used by view test1.v1</expected-error>
+ <expected-error>ASX1148: Cannot drop synonym test2.s2 being used by view test1.v1</expected-error>
+ <expected-error>ASX1148: Cannot drop view test2.v2 being used by view test1.v1</expected-error>
+ <expected-error>ASX1148: Cannot drop view test2.v2 being used by function test1.f1()</expected-error>
+ <source-location>false</source-location>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="view">
+ <compilation-unit name="view-1">
+ <output-dir compare="Text">view-1</output-dir>
+ </compilation-unit>
+ </test-case>
+ </test-group>
<test-group name="load">
<test-case FilePath="load">
<compilation-unit name="load_non-empty_index">
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/DatasetConfig.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/DatasetConfig.java
index f673d24..b85c0be 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/DatasetConfig.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/DatasetConfig.java
@@ -30,7 +30,8 @@
*/
public enum DatasetType {
INTERNAL,
- EXTERNAL
+ EXTERNAL,
+ VIEW
}
public enum IndexType {
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 1f25cc1..f9bcafc 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -233,7 +233,7 @@
UNKNOWN_FEED_POLICY(1146),
CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS(1147),
CANNOT_DROP_OBJECT_DEPENDENT_EXISTS(1148),
- ILLEGAL_FUNCTION_RECURSION(1149),
+ ILLEGAL_FUNCTION_OR_VIEW_RECURSION(1149),
ILLEGAL_FUNCTION_USE(1150),
NO_AUTH_PROVIDED_ENDPOINT_REQUIRED_FOR_ANONYMOUS_ACCESS(1151),
FULL_TEXT_CONFIG_NOT_FOUND(1152),
@@ -242,6 +242,9 @@
COMPILATION_INCOMPATIBLE_INDEX_TYPE(1155),
FULL_TEXT_CONFIG_ALREADY_EXISTS(1156),
FULL_TEXT_FILTER_ALREADY_EXISTS(1157),
+ COMPILATION_BAD_VIEW_DEFINITION(1158),
+ UNKNOWN_VIEW(1159),
+ VIEW_EXISTS(1160),
// Feed errors
DATAFLOW_ILLEGAL_STATE(3001),
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index e68db6a..58e8f1f 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -235,7 +235,7 @@
1146 = Cannot find feed policy with name %1$s
1147 = Cannot drop dataverse: %1$s %2$s being used by %3$s %4$s
1148 = Cannot drop %1$s %2$s being used by %3$s %4$s
-1149 = Illegal function recursion
+1149 = Illegal function or view recursion
1150 = Illegal use of function %1$s
1151 = No authentication credentials provided, '%1$s' field is required for anonymous access
1152 = Full-text config %1$s not found
@@ -244,6 +244,9 @@
1155 = Incompatible index type %1$s
1156 = Full-text config %1$s already exists
1157 = Full-text filter %1$s already exists
+1158 = Error compiling view %1$s. %2$s
+1159 = Cannot find view with name %1$s
+1160 = A view with this name %1$s already exists
# Feed Errors
3001 = Illegal state.
diff --git a/asterixdb/asterix-doc/src/main/grammar/sqlpp.ebnf b/asterixdb/asterix-doc/src/main/grammar/sqlpp.ebnf
index db89fe0..8dd08fa 100644
--- a/asterixdb/asterix-doc/src/main/grammar/sqlpp.ebnf
+++ b/asterixdb/asterix-doc/src/main/grammar/sqlpp.ebnf
@@ -149,6 +149,7 @@
| CreateIndex
| CreateSynonym
| CreateFunction
+ | CreateView
DataverseName ::= Identifier ("." Identifier)*
@@ -240,8 +241,10 @@
ExternalFunctionDef ::= ("RETURNS" TypeExpr)? "AS" StringLiteral ("," StringLiteral )* "AT" QualifiedName ("WITH" ObjectConstructor)?
+CreateView ::= "CREATE" ("OR" "REPLACE")? "VIEW" QualifiedName ("IF" "NOT" "EXISTS")? "AS" Selection
+
DropStmnt ::= "DROP" ("DATAVERSE" DataverseName
- | ("TYPE" |"DATASET" | "SYNONYM") QualifiedName
+ | ("TYPE" |"DATASET" |"SYNONYM" |"VIEW") QualifiedName
| "INDEX" DoubleQualifiedName
| "FUNCTION" FunctionSignature ) ("IF" "EXISTS")?
diff --git a/asterixdb/asterix-doc/src/main/markdown/sqlpp/0_toc.md b/asterixdb/asterix-doc/src/main/markdown/sqlpp/0_toc.md
index 47ed4e7..01ea63c 100644
--- a/asterixdb/asterix-doc/src/main/markdown/sqlpp/0_toc.md
+++ b/asterixdb/asterix-doc/src/main/markdown/sqlpp/0_toc.md
@@ -81,6 +81,7 @@
* [Create Index](#Indices)
* [Create Synonym](#Synonyms)
* [Create Function](#Create_function)
+ * [Create View](#Create_view)
* [Drop Statement](#Removal)
* [Load Statement](#Load_statement)
* [Modification Statements](#Modification_statements)
diff --git a/asterixdb/asterix-doc/src/main/markdown/sqlpp/7_ddl_dml.md b/asterixdb/asterix-doc/src/main/markdown/sqlpp/7_ddl_dml.md
index 1569d69..967b277 100644
--- a/asterixdb/asterix-doc/src/main/markdown/sqlpp/7_ddl_dml.md
+++ b/asterixdb/asterix-doc/src/main/markdown/sqlpp/7_ddl_dml.md
@@ -451,9 +451,10 @@
##### CreateSynonym

-The `CREATE SYNONYM` statement creates a synonym for a given dataset.
-This synonym may be used instead of the dataset name in `SELECT`, `INSERT`, `UPSERT`, `DELETE`, and `LOAD` statements.
-The target dataset does not need to exist when the synonym is created.
+The `CREATE SYNONYM` statement creates a synonym for a given dataset or a view.
+This synonym may be used instead of the dataset name in `SELECT`, `INSERT`, `UPSERT`, `DELETE`, and `LOAD` statements,
+or instead of the view name in `SELECT` statements.
+The target dataset or view does not need to exist when the synonym is created.
A synonym may be created for another synonym.
##### Example
@@ -519,6 +520,25 @@
CREATE FUNCTION sentiment(a) AS "sentiment_mod", "sent_model.sentiment" AT pylib;
+#### <a id="Create_view">Create View</a>
+
+The `CREATE VIEW` statement creates a **named** view that can then be used in queries.
+The body of a view can be any `SELECT` statement.
+
+##### CreateView
+
+
+##### Example
+
+ CREATE DATASET customers(customersType) PRIMARY KEY custid;
+
+ CREATE VIEW customersView AS
+ SELECT c.custid, c.name
+ FROM customers AS c
+ WHERE c.address.city = "Boston, MA";
+
+ SELECT * FROM customersView;
+
### <a id="Removal">Drop Statement</a>
##### DropStmnt
@@ -555,6 +575,8 @@
DROP SYNONYM customersSynonym;
+ DROP VIEW customersView;
+
DROP DATAVERSE CommerceData;
When an artifact is dropped, it will be droppped from the current dataverse if none is specified
diff --git a/asterixdb/asterix-doc/src/main/markdown/sqlpp/appendix_3_resolution.md b/asterixdb/asterix-doc/src/main/markdown/sqlpp/appendix_3_resolution.md
index a4acbb0..4393f5e 100644
--- a/asterixdb/asterix-doc/src/main/markdown/sqlpp/appendix_3_resolution.md
+++ b/asterixdb/asterix-doc/src/main/markdown/sqlpp/appendix_3_resolution.md
@@ -215,7 +215,7 @@
The rules for resolving the leftmost identifier are:
1. _In a `FROM` clause_: Names in a `FROM` clause identify the collections over which the query block will iterate.
- These collections may be stored datasets or may be the results of nested query blocks.
+ These collections may be stored datasets, views, synonyms, or may be the results of nested query blocks.
A stored dataset may be in a named dataverse or in the default dataverse.
Thus, if the two-part name `a.b` is in a `FROM` clause, a might represent a dataverse and `b` might represent a dataset in that dataverse.
Another example of a two-part name in a `FROM` clause is `FROM orders AS o, o.items AS i`.
@@ -229,12 +229,13 @@
- (1B): Otherwise, if the identifier is the first part of a two-part name like `a.b`, the name is treated as `dataverse.dataset`.
If the identifier stands alone as a one-part name, it is treated as the name of a dataset in the default dataverse.
If the designated dataset exists then the identifier is resolved to that dataset,
- otherwise if a synonym with given name exists then the identifier is resolved to the target dataset of that
+ othwerise if a view with given name exists then the identifier is resolved to that view,
+ otherwise if a synonym with given name exists then the identifier is resolved to the target dataset or the target view of that
synonym (potentially recursively if this synonym points to another synonym). An error will result if the designated
- dataset or a synonym with this name does not exist.
+ dataset, view, or a synonym with this name does not exist.
- Datasets take precedence over synonyms, so if both a dataset and a synonym have the same name then the
- resolution is to the dataset.
+ Datasets and views take precedence over synonyms, so if both a dataset (or a view) and a synonym have the same name then the
+ resolution is to the dataset. Note that there cannot be a dataset and a view with the same name.
2. _Elsewhere in a query block_: In clauses other than `FROM`, a name typically identifies a field of some object.
For example, if the expression `a.b` is in a `SELECT` or `WHERE` clause, it's likely that `a` represents an object and `b` represents a field in that object.
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
index 3df490c..1645d76 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
@@ -23,7 +23,9 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.ViewDecl;
import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.api.exceptions.Warning;
@@ -38,6 +40,8 @@
FunctionDecl parseFunctionBody(FunctionSignature signature, List<String> paramNames, boolean isStored)
throws CompilationException;
+ ViewDecl parseViewBody(DatasetFullyQualifiedName viewName) throws CompilationException;
+
/**
* Gets the warnings generated during parsing
*/
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
index f28de55..6099cb6 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
@@ -25,6 +25,9 @@
import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.VariableExpr;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.statement.ViewDecl;
import org.apache.asterix.lang.common.struct.VarIdentifier;
public interface IQueryRewriter {
@@ -37,13 +40,12 @@
* rewriting context
* @param allowNonStoredUdfCalls
* whether calls to non-stored user-defined functions should be resolved
- * @param inlineUdfs
+ * @param inlineUdfsAndViews
* whether user defined functions should be inlines
* @param externalVars
- * statement parameters (external variables)
*/
void rewrite(LangRewritingContext context, IReturningStatement topExpr, boolean allowNonStoredUdfCalls,
- boolean inlineUdfs, Collection<VarIdentifier> externalVars) throws CompilationException;
+ boolean inlineUdfsAndViews, Collection<VarIdentifier> externalVars) throws CompilationException;
/**
* Find the function calls used by a given expression
@@ -55,4 +57,12 @@
* Find all external variables (positional and named variables) in given expression
*/
Set<VariableExpr> getExternalVariables(Expression expr) throws CompilationException;
+
+ VarIdentifier toExternalVariableName(String statementParameterName);
+
+ String toFunctionParameterName(VarIdentifier paramVar);
+
+ Query createFunctionAccessorQuery(FunctionDecl functionDecl);
+
+ Query createViewAccessorQuery(ViewDecl viewDecl);
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IStatementRewriter.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IStatementRewriter.java
index 9d983b0..f50d040 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IStatementRewriter.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IStatementRewriter.java
@@ -19,7 +19,6 @@
package org.apache.asterix.lang.common.base;
import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.metadata.declared.MetadataProvider;
public interface IStatementRewriter {
@@ -36,8 +35,4 @@
* a metadata provider
*/
void rewrite(Statement statement, MetadataProvider metadataProvider) throws CompilationException;
-
- String toExternalVariableName(String statementParameterName);
-
- String toFunctionParameterName(VarIdentifier paramVar);
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
index 182fc08..663074e 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
@@ -58,6 +58,7 @@
UPSERT,
UPDATE,
FUNCTION_DECL,
+ VIEW_DECL,
LOAD,
NODEGROUP_DECL,
NODEGROUP_DROP,
@@ -68,6 +69,7 @@
WRITE,
CREATE_INDEX,
CREATE_DATAVERSE,
+ CREATE_VIEW,
CREATE_FULL_TEXT_FILTER,
CREATE_FULL_TEXT_CONFIG,
INDEX_DROP,
@@ -89,6 +91,7 @@
LIBRARY_DROP,
CREATE_SYNONYM,
SYNONYM_DROP,
+ VIEW_DROP,
COMPACT,
EXTERNAL_DATASET_REFRESH,
SUBSCRIBE_FEED,
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java
index 675d0d3..95cccb0 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/LangRewritingContext.java
@@ -18,14 +18,16 @@
*/
package org.apache.asterix.lang.common.rewrites;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.ViewDecl;
import org.apache.asterix.lang.common.struct.VarIdentifier;
-import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.hyracks.algebricks.core.algebra.base.Counter;
import org.apache.hyracks.api.exceptions.IWarningCollector;
@@ -34,15 +36,17 @@
private final MetadataProvider metadataProvider;
private final IWarningCollector warningCollector;
private final Map<FunctionSignature, FunctionDecl> declaredFunctions;
+ private final Map<DatasetFullyQualifiedName, ViewDecl> declaredViews;
private final Counter varCounter;
private int systemVarCounter = 1;
private final Map<Integer, VarIdentifier> oldVarIdToNewVarId = new HashMap<>();
public LangRewritingContext(MetadataProvider metadataProvider, List<FunctionDecl> declaredFunctions,
- IWarningCollector warningCollector, int varCounter) {
+ List<ViewDecl> declaredViews, IWarningCollector warningCollector, int varCounter) {
this.metadataProvider = metadataProvider;
this.warningCollector = warningCollector;
- this.declaredFunctions = FunctionUtil.getFunctionMap(declaredFunctions);
+ this.declaredFunctions = createMap(declaredFunctions, FunctionDecl::getSignature);
+ this.declaredViews = createMap(declaredViews, ViewDecl::getViewName);
this.varCounter = new Counter(varCounter);
}
@@ -93,4 +97,19 @@
public Map<FunctionSignature, FunctionDecl> getDeclaredFunctions() {
return declaredFunctions;
}
+
+ public Map<DatasetFullyQualifiedName, ViewDecl> getDeclaredViews() {
+ return declaredViews;
+ }
+
+ private static <K, V> Map<K, V> createMap(List<V> values, java.util.function.Function<V, K> keyMapper) {
+ if (values == null || values.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map<K, V> result = new HashMap<>();
+ for (V v : values) {
+ result.put(keyMapper.apply(v), v);
+ }
+ return Collections.unmodifiableMap(result);
+ }
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateViewStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateViewStatement.java
new file mode 100644
index 0000000..97420ea
--- /dev/null
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateViewStatement.java
@@ -0,0 +1,94 @@
+/*
+ * 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.lang.common.statement;
+
+import static org.apache.asterix.lang.common.base.Statement.Kind.CREATE_VIEW;
+
+import java.util.Objects;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.lang.common.base.AbstractStatement;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
+
+public final class CreateViewStatement extends AbstractStatement {
+
+ private final DataverseName dataverseName;
+
+ private final String viewName;
+
+ private final String viewBody;
+
+ private final Expression viewBodyExpression;
+
+ private final boolean replaceIfExists;
+
+ private final boolean ifNotExists;
+
+ public CreateViewStatement(DataverseName dataverseName, String viewName, String viewBody,
+ Expression viewBodyExpression, boolean replaceIfExists, boolean ifNotExists) {
+ this.dataverseName = dataverseName;
+ this.viewName = Objects.requireNonNull(viewName);
+ this.viewBody = Objects.requireNonNull(viewBody);
+ this.viewBodyExpression = Objects.requireNonNull(viewBodyExpression);
+ this.replaceIfExists = replaceIfExists;
+ this.ifNotExists = ifNotExists;
+ }
+
+ public DataverseName getDataverseName() {
+ return dataverseName;
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+ public String getViewBody() {
+ return viewBody;
+ }
+
+ public Expression getViewBodyExpression() {
+ return viewBodyExpression;
+ }
+
+ public boolean getReplaceIfExists() {
+ return replaceIfExists;
+ }
+
+ public boolean getIfNotExists() {
+ return ifNotExists;
+ }
+
+ @Override
+ public Kind getKind() {
+ return CREATE_VIEW;
+ }
+
+ @Override
+ public byte getCategory() {
+ return Category.DDL;
+ }
+
+ @Override
+ public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws CompilationException {
+ return visitor.visit(this, arg);
+ }
+}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ViewDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ViewDecl.java
new file mode 100644
index 0000000..a3b1937
--- /dev/null
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ViewDecl.java
@@ -0,0 +1,88 @@
+/*
+ * 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.lang.common.statement;
+
+import java.util.Objects;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
+import org.apache.asterix.lang.common.base.AbstractStatement;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
+
+public final class ViewDecl extends AbstractStatement {
+
+ private final DatasetFullyQualifiedName viewName;
+
+ private Expression viewBody;
+
+ private Expression viewBodyNormalized;
+
+ public ViewDecl(DatasetFullyQualifiedName viewName, Expression viewBody) {
+ this.viewName = Objects.requireNonNull(viewName);
+ this.viewBody = Objects.requireNonNull(viewBody);
+ }
+
+ public DatasetFullyQualifiedName getViewName() {
+ return viewName;
+ }
+
+ public Expression getViewBody() {
+ return viewBody;
+ }
+
+ public void setViewBody(Expression expr) {
+ viewBody = expr;
+ viewBodyNormalized = null;
+ }
+
+ public Expression getNormalizedViewBody() {
+ return viewBodyNormalized;
+ }
+
+ public void setNormalizedViewBody(Expression expr) {
+ viewBodyNormalized = expr;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ ViewDecl viewDecl = (ViewDecl) o;
+ return viewName.equals(viewDecl.viewName);
+ }
+
+ @Override
+ public Kind getKind() {
+ return Kind.VIEW_DECL;
+ }
+
+ @Override
+ public byte getCategory() {
+ return Category.QUERY;
+ }
+
+ @Override
+ public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws CompilationException {
+ return visitor.visit(this, arg);
+ }
+}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ViewDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ViewDropStatement.java
new file mode 100644
index 0000000..9f8577c
--- /dev/null
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ViewDropStatement.java
@@ -0,0 +1,69 @@
+/*
+ * 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.lang.common.statement;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.lang.common.base.AbstractStatement;
+import org.apache.asterix.lang.common.base.Statement;
+import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
+
+public class ViewDropStatement extends AbstractStatement {
+
+ private final DataverseName dataverseName;
+
+ private final Identifier viewName;
+
+ private final boolean ifExists;
+
+ public ViewDropStatement(DataverseName dataverseName, Identifier viewName, boolean ifExists) {
+ this.dataverseName = dataverseName;
+ this.viewName = viewName;
+ this.ifExists = ifExists;
+ }
+
+ public DataverseName getDataverseName() {
+ return dataverseName;
+ }
+
+ public Identifier getViewName() {
+ return viewName;
+ }
+
+ public boolean getIfExists() {
+ return ifExists;
+ }
+
+ @Override
+ public Kind getKind() {
+ return Statement.Kind.VIEW_DROP;
+ }
+
+ @Override
+ public byte getCategory() {
+ return Category.DDL;
+ }
+
+ @Override
+ public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws CompilationException {
+ return visitor.visit(this, arg);
+ }
+}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
index dd21152..1fc7234 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
@@ -18,14 +18,24 @@
*/
package org.apache.asterix.lang.common.util;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
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.common.metadata.DatasetFullyQualifiedName;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.lang.common.base.AbstractStatement;
import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.base.Literal;
+import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.FieldBinding;
import org.apache.asterix.lang.common.expression.ListConstructor;
import org.apache.asterix.lang.common.expression.LiteralExpr;
@@ -33,6 +43,9 @@
import org.apache.asterix.lang.common.literal.DoubleLiteral;
import org.apache.asterix.lang.common.literal.LongIntegerLiteral;
import org.apache.asterix.lang.common.literal.StringLiteral;
+import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.lang.common.visitor.GatherFunctionCallsVisitor;
import org.apache.asterix.object.base.AdmArrayNode;
import org.apache.asterix.object.base.AdmBigIntNode;
import org.apache.asterix.object.base.AdmBooleanNode;
@@ -41,6 +54,11 @@
import org.apache.asterix.object.base.AdmObjectNode;
import org.apache.asterix.object.base.AdmStringNode;
import org.apache.asterix.object.base.IAdmNode;
+import org.apache.hyracks.algebricks.common.utils.Triple;
+
+import com.google.common.graph.GraphBuilder;
+import com.google.common.graph.Graphs;
+import com.google.common.graph.MutableGraph;
public class ExpressionUtils {
private ExpressionUtils() {
@@ -113,4 +131,119 @@
}
return null;
}
+
+ public static Boolean getBooleanLiteral(Expression arg) {
+ if (arg.getKind() == Expression.Kind.LITERAL_EXPRESSION) {
+ Literal item = ((LiteralExpr) arg).getValue();
+ switch (item.getLiteralType()) {
+ case TRUE:
+ return true;
+ case FALSE:
+ return false;
+ }
+ }
+ return null;
+ }
+
+ public static void collectDependencies(Expression expression, IQueryRewriter rewriter,
+ List<Triple<DataverseName, String, String>> outDatasetDependencies,
+ List<Triple<DataverseName, String, String>> outSynonymDependencies,
+ List<Triple<DataverseName, String, String>> outFunctionDependencies) throws CompilationException {
+ // Duplicate elimination
+ Set<DatasetFullyQualifiedName> seenDatasets = new HashSet<>();
+ Set<DatasetFullyQualifiedName> seenSynonyms = new HashSet<>();
+ Set<FunctionSignature> seenFunctions = new HashSet<>();
+ List<AbstractCallExpression> functionCalls = new ArrayList<>();
+ rewriter.getFunctionCalls(expression, functionCalls);
+
+ for (AbstractCallExpression functionCall : functionCalls) {
+ switch (functionCall.getKind()) {
+ case CALL_EXPRESSION:
+ FunctionSignature signature = functionCall.getFunctionSignature();
+ if (FunctionUtil.isBuiltinFunctionSignature(signature)) {
+ if (FunctionUtil.isBuiltinDatasetFunction(signature)) {
+ Triple<DatasetFullyQualifiedName, Boolean, DatasetFullyQualifiedName> dsArgs =
+ FunctionUtil.parseDatasetFunctionArguments(functionCall);
+ DatasetFullyQualifiedName synonymReference = dsArgs.third;
+ if (synonymReference != null) {
+ // resolved via synonym -> store synonym name as a dependency
+ if (seenSynonyms.add(synonymReference)) {
+ outSynonymDependencies.add(new Triple<>(synonymReference.getDataverseName(),
+ synonymReference.getDatasetName(), null));
+ }
+ } else {
+ // resolved directly -> store dataset (or view) name as a dependency
+ DatasetFullyQualifiedName datasetReference = dsArgs.first;
+ if (seenDatasets.add(datasetReference)) {
+ outDatasetDependencies.add(new Triple<>(datasetReference.getDataverseName(),
+ datasetReference.getDatasetName(), null));
+ }
+ }
+ }
+ } else {
+ if (seenFunctions.add(signature)) {
+ outFunctionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
+ Integer.toString(signature.getArity())));
+ }
+ }
+ break;
+ case WINDOW_EXPRESSION:
+ // there cannot be used-defined window functions
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
+ functionCall.getSourceLocation(), functionCall.getFunctionSignature().toString(false));
+ }
+ }
+ }
+
+ public static boolean hasFunctionOrViewRecursion(Map<FunctionSignature, FunctionDecl> functionDeclMap,
+ Map<DatasetFullyQualifiedName, ViewDecl> viewDeclMap,
+ java.util.function.Function<Collection<AbstractCallExpression>, GatherFunctionCallsVisitor> callVisitorFactory)
+ throws CompilationException {
+ List<AbstractCallExpression> callList = new ArrayList<>();
+ GatherFunctionCallsVisitor callVisitor = callVisitorFactory.apply(callList);
+ MutableGraph<AbstractStatement> callGraph = GraphBuilder.directed().allowsSelfLoops(true).build();
+ for (FunctionDecl from : functionDeclMap.values()) {
+ callList.clear();
+ from.getNormalizedFuncBody().accept(callVisitor, null);
+ for (AbstractCallExpression callExpr : callList) {
+ addToCallGraph(callGraph, from, callExpr, functionDeclMap, viewDeclMap);
+ }
+ }
+ for (ViewDecl from : viewDeclMap.values()) {
+ callList.clear();
+ from.getNormalizedViewBody().accept(callVisitor, null);
+ for (AbstractCallExpression callExpr : callList) {
+ addToCallGraph(callGraph, from, callExpr, functionDeclMap, viewDeclMap);
+ }
+ }
+ return Graphs.hasCycle(callGraph);
+ }
+
+ private static void addToCallGraph(MutableGraph<AbstractStatement> callGraph, AbstractStatement from,
+ AbstractCallExpression callExpr, Map<FunctionSignature, FunctionDecl> functionDeclMap,
+ Map<DatasetFullyQualifiedName, ViewDecl> viewDeclMap) throws CompilationException {
+ if (callExpr.getKind() == Expression.Kind.CALL_EXPRESSION) {
+ FunctionSignature callSignature = callExpr.getFunctionSignature();
+ if (FunctionUtil.isBuiltinFunctionSignature(callSignature)) {
+ if (FunctionUtil.isBuiltinDatasetFunction(callSignature)) {
+ Triple<DatasetFullyQualifiedName, Boolean, DatasetFullyQualifiedName> dsArgs =
+ FunctionUtil.parseDatasetFunctionArguments(callExpr);
+ if (Boolean.TRUE.equals(dsArgs.second)) {
+ DatasetFullyQualifiedName viewName = dsArgs.first;
+ ViewDecl vdTo = viewDeclMap.get(viewName);
+ if (vdTo != null) {
+ callGraph.putEdge(from, vdTo);
+ }
+ }
+ }
+ } else {
+ FunctionDecl fdTo = functionDeclMap.get(callSignature);
+ if (fdTo != null) {
+ callGraph.putEdge(from, fdTo);
+ }
+ }
+ }
+ }
}
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 ded91af..42a35f3 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
@@ -23,12 +23,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.function.BiFunction;
import org.apache.asterix.common.exceptions.AsterixException;
@@ -36,19 +33,18 @@
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.DatasetFullyQualifiedName;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.IParser;
import org.apache.asterix.lang.common.base.IParserFactory;
import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.expression.AbstractCallExpression;
-import org.apache.asterix.lang.common.expression.CallExpr;
import org.apache.asterix.lang.common.expression.OrderedListTypeDefinition;
import org.apache.asterix.lang.common.expression.TypeExpression;
import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
import org.apache.asterix.lang.common.expression.UnorderedListTypeDefinition;
import org.apache.asterix.lang.common.statement.FunctionDecl;
-import org.apache.asterix.lang.common.visitor.GatherFunctionCallsVisitor;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.BuiltinTypeMap;
import org.apache.asterix.metadata.entities.Dataverse;
@@ -60,7 +56,6 @@
import org.apache.asterix.om.utils.ConstantExpressionUtil;
import org.apache.commons.lang3.mutable.Mutable;
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.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
@@ -68,10 +63,6 @@
import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.api.exceptions.SourceLocation;
-import com.google.common.graph.GraphBuilder;
-import com.google.common.graph.Graphs;
-import com.google.common.graph.MutableGraph;
-
public class FunctionUtil {
public static final String IMPORT_PRIVATE_FUNCTIONS = "import-private-functions";
@@ -208,79 +199,22 @@
};
}
- public static void checkFunctionRecursion(Map<FunctionSignature, FunctionDecl> functionDeclMap,
- java.util.function.Function<Collection<AbstractCallExpression>, GatherFunctionCallsVisitor> gfcFactory,
- SourceLocation sourceLoc) throws CompilationException {
- List<AbstractCallExpression> callList = new ArrayList<>();
- GatherFunctionCallsVisitor gfc = gfcFactory.apply(callList);
- MutableGraph<FunctionDecl> graph = GraphBuilder.directed().allowsSelfLoops(true).build();
- for (FunctionDecl fdFrom : functionDeclMap.values()) {
- callList.clear();
- fdFrom.getNormalizedFuncBody().accept(gfc, null);
- for (AbstractCallExpression callExpr : callList) {
- if (callExpr.getKind() == Expression.Kind.CALL_EXPRESSION) {
- FunctionSignature callSignature = callExpr.getFunctionSignature();
- FunctionDecl fdTo = functionDeclMap.get(callSignature);
- if (fdTo != null) {
- graph.putEdge(fdFrom, fdTo);
- }
- }
- }
+ public static List<List<Triple<DataverseName, String, String>>> getFunctionDependencies(FunctionDecl fd,
+ IQueryRewriter rewriter) throws CompilationException {
+ Expression normBody = fd.getNormalizedFuncBody();
+ if (normBody == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, fd.getSourceLocation(),
+ fd.getSignature().toString());
}
- if (Graphs.hasCycle(graph)) {
- throw new CompilationException(ErrorCode.ILLEGAL_FUNCTION_RECURSION, sourceLoc);
- }
- }
- public static List<List<Triple<DataverseName, String, String>>> getFunctionDependencies(IQueryRewriter rewriter,
- Expression expression) throws CompilationException {
- List<AbstractCallExpression> functionCalls = new ArrayList<>();
- rewriter.getFunctionCalls(expression, functionCalls);
- // Duplicate elimination
- Set<FunctionSignature> seenFunctions = new HashSet<>();
- Set<Pair<DataverseName, String>> seenDatasets = new HashSet<>();
- Set<Pair<DataverseName, String>> seenSynonyms = new HashSet<>();
- //Get the List of used functions and used datasets
+ // Get the list of used functions and used datasets
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)) {
- 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);
- if (seenSynonyms.add(synonymReference)) {
- 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);
- if (seenDatasets.add(datasetReference)) {
- datasetDependencies
- .add(new Triple<>(datasetReference.first, datasetReference.second, null));
- }
- }
- } else if (BuiltinFunctions.getBuiltinFunctionInfo(signature.createFunctionIdentifier()) == null) {
- if (seenFunctions.add(signature)) {
- functionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
- Integer.toString(signature.getArity())));
- }
- }
- break;
- case WINDOW_EXPRESSION:
- // there cannot be used-defined window functions
- break;
- default:
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expression.getSourceLocation(),
- functionCall.getFunctionSignature().toString(false));
- }
- }
+ List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
+ ExpressionUtils.collectDependencies(normBody, rewriter, datasetDependencies, synonymDependencies,
+ functionDependencies);
+
+ List<Triple<DataverseName, String, String>> typeDependencies = Collections.emptyList();
return Function.createDependencies(datasetDependencies, functionDependencies, typeDependencies,
synonymDependencies);
}
@@ -303,27 +237,27 @@
&& Objects.equals(FN_DATASET_NAME, fs.getName());
}
- public static Pair<DataverseName, String> parseDatasetFunctionArguments(CallExpr datasetFn)
- throws CompilationException {
- return parseDatasetFunctionArguments(datasetFn, 0);
+ public static Triple<DatasetFullyQualifiedName, Boolean, DatasetFullyQualifiedName> parseDatasetFunctionArguments(
+ AbstractCallExpression datasetFn) throws CompilationException {
+ List<Expression> argList = datasetFn.getExprList();
+ DatasetFullyQualifiedName datasetOrViewName = parseDatasetFunctionArguments(argList, 0,
+ datasetFn.getSourceLocation(), ExpressionUtils::getStringLiteral);
+ boolean isView = argList.size() > 2 && Boolean.TRUE.equals(ExpressionUtils.getBooleanLiteral(argList.get(2)));
+ DatasetFullyQualifiedName synonymName = argList.size() > 3 ? parseDatasetFunctionArguments(argList, 3,
+ datasetFn.getSourceLocation(), ExpressionUtils::getStringLiteral) : null;
+ return new Triple<>(datasetOrViewName, isView, synonymName);
}
- 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)
+ public static DatasetFullyQualifiedName parseDatasetFunctionArguments(AbstractFunctionCallExpression datasetFn)
throws CompilationException {
return parseDatasetFunctionArguments(datasetFn.getArguments(), 0, datasetFn.getSourceLocation(),
FunctionUtil::getStringConstant);
}
- private static <T> Pair<DataverseName, String> parseDatasetFunctionArguments(List<T> datasetFnArgs, int startPos,
- SourceLocation sourceLoc, java.util.function.Function<T, String> argExtractFunction)
+ private static <T> DatasetFullyQualifiedName parseDatasetFunctionArguments(List<T> datasetFnArgs, int startPos,
+ SourceLocation sourceLoc, java.util.function.Function<T, String> stringAccessor)
throws CompilationException {
- String dataverseNameArg = argExtractFunction.apply(datasetFnArgs.get(startPos));
+ String dataverseNameArg = stringAccessor.apply(datasetFnArgs.get(startPos));
if (dataverseNameArg == null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, "Invalid argument to dataset()");
}
@@ -333,11 +267,11 @@
} catch (AsterixException e) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, e, "Invalid argument to dataset()");
}
- String datasetName = argExtractFunction.apply(datasetFnArgs.get(startPos + 1));
+ String datasetName = stringAccessor.apply(datasetFnArgs.get(startPos + 1));
if (datasetName == null) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, sourceLoc, "Invalid argument to dataset()");
}
- return new Pair<>(dataverseName, datasetName);
+ return new DatasetFullyQualifiedName(dataverseName, datasetName);
}
private static String getStringConstant(Mutable<ILogicalExpression> arg) {
@@ -349,17 +283,6 @@
return (value != null) && Boolean.parseBoolean(value.toLowerCase());
}
- public static Map<FunctionSignature, FunctionDecl> getFunctionMap(List<FunctionDecl> declaredFunctions) {
- if (declaredFunctions == null || declaredFunctions.isEmpty()) {
- return Collections.emptyMap();
- }
- Map<FunctionSignature, FunctionDecl> result = new HashMap<>();
- for (FunctionDecl fd : declaredFunctions) {
- result.put(fd.getSignature(), fd);
- }
- return result;
- }
-
public static FunctionDecl parseStoredFunction(Function function, IParserFactory parserFactory,
IWarningCollector warningCollector, SourceLocation sourceLoc) throws CompilationException {
if (!function.getLanguage().equals(parserFactory.getLanguage())) {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ViewUtil.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ViewUtil.java
new file mode 100644
index 0000000..446b0ad
--- /dev/null
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ViewUtil.java
@@ -0,0 +1,82 @@
+/*
+ * 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.lang.common.util;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.IParser;
+import org.apache.asterix.lang.common.base.IParserFactory;
+import org.apache.asterix.lang.common.base.IQueryRewriter;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.metadata.entities.ViewDetails;
+import org.apache.hyracks.algebricks.common.utils.Triple;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+
+public final class ViewUtil {
+
+ private ViewUtil() {
+ }
+
+ public static ViewDecl parseStoredView(DatasetFullyQualifiedName viewName, ViewDetails view,
+ IParserFactory parserFactory, IWarningCollector warningCollector, SourceLocation sourceLoc)
+ throws CompilationException {
+ IParser parser = parserFactory.createParser(new StringReader(view.getViewBody()));
+ try {
+ ViewDecl viewDecl = parser.parseViewBody(viewName);
+ viewDecl.setSourceLocation(sourceLoc);
+ if (warningCollector != null) {
+ parser.getWarnings(warningCollector);
+ }
+ return viewDecl;
+ } catch (CompilationException e) {
+ throw new CompilationException(ErrorCode.COMPILATION_BAD_VIEW_DEFINITION, e, sourceLoc, viewName,
+ e.getMessage());
+ }
+ }
+
+ public static List<List<Triple<DataverseName, String, String>>> getViewDependencies(ViewDecl viewDecl,
+ IQueryRewriter rewriter) throws CompilationException {
+ Expression normBody = viewDecl.getNormalizedViewBody();
+ if (normBody == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, viewDecl.getSourceLocation(),
+ viewDecl.getViewName().toString());
+ }
+
+ // Get the list of used functions and used datasets
+ List<Triple<DataverseName, String, String>> datasetDependencies = new ArrayList<>();
+ List<Triple<DataverseName, String, String>> synonymDependencies = new ArrayList<>();
+ List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
+ ExpressionUtils.collectDependencies(normBody, rewriter, datasetDependencies, synonymDependencies,
+ functionDependencies);
+
+ List<Triple<DataverseName, String, String>> typeDependencies = Collections.emptyList();
+ return ViewDetails.createDependencies(datasetDependencies, functionDependencies, typeDependencies,
+ synonymDependencies);
+ }
+}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
index cba6bb5..7fe7140 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
@@ -19,6 +19,7 @@
package org.apache.asterix.lang.common.visitor;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -26,6 +27,7 @@
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.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.Expression.Kind;
import org.apache.asterix.lang.common.base.ILangExpression;
@@ -52,6 +54,7 @@
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.statement.ViewDecl;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.QuantifiedPair;
import org.apache.asterix.lang.common.struct.VarIdentifier;
@@ -59,6 +62,7 @@
import org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisitor;
import org.apache.asterix.om.functions.BuiltinFunctions;
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;
@@ -68,12 +72,15 @@
protected final Map<FunctionSignature, FunctionDecl> usedUDFs;
+ protected final Map<DatasetFullyQualifiedName, ViewDecl> usedViews;
+
protected final CloneAndSubstituteVariablesVisitor cloneVisitor;
public AbstractInlineUdfsVisitor(LangRewritingContext context, Map<FunctionSignature, FunctionDecl> usedUDFs,
- CloneAndSubstituteVariablesVisitor cloneVisitor) {
+ Map<DatasetFullyQualifiedName, ViewDecl> usedViews, CloneAndSubstituteVariablesVisitor cloneVisitor) {
this.context = context;
this.usedUDFs = usedUDFs;
+ this.usedViews = usedViews;
this.cloneVisitor = cloneVisitor;
}
@@ -89,18 +96,12 @@
@Override
public Boolean visit(Query q, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(q.getBody());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(q.getBody());
q.setBody(p.second);
return p.first;
}
@Override
- public Boolean visit(FunctionDecl fd, Void arg) throws CompilationException {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, fd.getSourceLocation(),
- fd.getSignature().toString());
- }
-
- @Override
public Boolean visit(ListConstructor lc, Void arg) throws CompilationException {
Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(lc.getExprList());
lc.setExprList(p.second);
@@ -111,10 +112,10 @@
public Boolean visit(RecordConstructor rc, Void arg) throws CompilationException {
boolean changed = false;
for (FieldBinding b : rc.getFbList()) {
- Pair<Boolean, Expression> leftExprInlined = inlineUdfsInExpr(b.getLeftExpr());
+ Pair<Boolean, Expression> leftExprInlined = inlineUdfsAndViewsInExpr(b.getLeftExpr());
b.setLeftExpr(leftExprInlined.second);
changed = changed || leftExprInlined.first;
- Pair<Boolean, Expression> rightExprInlined = inlineUdfsInExpr(b.getRightExpr());
+ Pair<Boolean, Expression> rightExprInlined = inlineUdfsAndViewsInExpr(b.getRightExpr());
b.setRightExpr(rightExprInlined.second);
changed = changed || rightExprInlined.first;
}
@@ -127,7 +128,7 @@
callExpr.setExprList(p.second);
boolean changed = p.first;
if (callExpr.hasAggregateFilterExpr()) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(callExpr.getAggregateFilterExpr());
+ Pair<Boolean, Expression> be = inlineUdfsAndViewsInExpr(callExpr.getAggregateFilterExpr());
callExpr.setAggregateFilterExpr(be.second);
changed |= be.first;
}
@@ -143,25 +144,25 @@
@Override
public Boolean visit(FieldAccessor fa, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(fa.getExpr());
fa.setExpr(p.second);
return p.first;
}
@Override
public Boolean visit(IndexAccessor fa, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(fa.getExpr());
fa.setExpr(p.second);
return p.first;
}
@Override
public Boolean visit(IfExpr ifexpr, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(ifexpr.getCondExpr());
+ Pair<Boolean, Expression> p1 = inlineUdfsAndViewsInExpr(ifexpr.getCondExpr());
ifexpr.setCondExpr(p1.second);
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(ifexpr.getThenExpr());
+ Pair<Boolean, Expression> p2 = inlineUdfsAndViewsInExpr(ifexpr.getThenExpr());
ifexpr.setThenExpr(p2.second);
- Pair<Boolean, Expression> p3 = inlineUdfsInExpr(ifexpr.getElseExpr());
+ Pair<Boolean, Expression> p3 = inlineUdfsAndViewsInExpr(ifexpr.getElseExpr());
ifexpr.setElseExpr(p3.second);
return p1.first || p2.first || p3.first;
}
@@ -170,27 +171,27 @@
public Boolean visit(QuantifiedExpression qe, Void arg) throws CompilationException {
boolean changed = false;
for (QuantifiedPair t : qe.getQuantifiedList()) {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(t.getExpr());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(t.getExpr());
t.setExpr(p.second);
if (p.first) {
changed = true;
}
}
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(qe.getSatisfiesExpr());
+ Pair<Boolean, Expression> p2 = inlineUdfsAndViewsInExpr(qe.getSatisfiesExpr());
qe.setSatisfiesExpr(p2.second);
return changed || p2.first;
}
@Override
public Boolean visit(LetClause lc, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(lc.getBindingExpr());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(lc.getBindingExpr());
lc.setBindingExpr(p.second);
return p.first;
}
@Override
public Boolean visit(WhereClause wc, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(wc.getWhereExpr());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(wc.getWhereExpr());
wc.setWhereExpr(p.second);
return p.first;
}
@@ -235,12 +236,12 @@
public Boolean visit(LimitClause lc, Void arg) throws CompilationException {
boolean changed = false;
if (lc.hasLimitExpr()) {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(lc.getLimitExpr());
+ Pair<Boolean, Expression> p1 = inlineUdfsAndViewsInExpr(lc.getLimitExpr());
lc.setLimitExpr(p1.second);
changed = p1.first;
}
if (lc.hasOffset()) {
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(lc.getOffset());
+ Pair<Boolean, Expression> p2 = inlineUdfsAndViewsInExpr(lc.getOffset());
lc.setOffset(p2.second);
changed |= p2.first;
}
@@ -267,53 +268,101 @@
boolean changed = false;
Expression returnExpression = insert.getReturnExpression();
if (returnExpression != null) {
- Pair<Boolean, Expression> rewrittenReturnExpr = inlineUdfsInExpr(returnExpression);
+ Pair<Boolean, Expression> rewrittenReturnExpr = inlineUdfsAndViewsInExpr(returnExpression);
insert.setReturnExpression(rewrittenReturnExpr.second);
changed |= rewrittenReturnExpr.first;
}
- Pair<Boolean, Expression> rewrittenBodyExpression = inlineUdfsInExpr(insert.getBody());
+ Pair<Boolean, Expression> rewrittenBodyExpression = inlineUdfsAndViewsInExpr(insert.getBody());
insert.setBody(rewrittenBodyExpression.second);
return changed || rewrittenBodyExpression.first;
}
- protected Pair<Boolean, Expression> inlineUdfsInExpr(Expression expr) throws CompilationException {
+ protected Pair<Boolean, Expression> inlineUdfsAndViewsInExpr(Expression expr) throws CompilationException {
if (expr.getKind() != Kind.CALL_EXPRESSION) {
boolean r = expr.accept(this, null);
return new Pair<>(r, expr);
}
CallExpr f = (CallExpr) expr;
boolean r = expr.accept(this, null);
+
+ List<LetClause> letClauses;
+ VariableSubstitutionEnvironment bodyVarSubst;
+ Expression normBodyExpr;
+
FunctionSignature fs = f.getFunctionSignature();
if (FunctionUtil.isBuiltinFunctionSignature(fs)) {
- return new Pair<>(r, expr);
+ if (!FunctionUtil.isBuiltinDatasetFunction(fs)) {
+ return new Pair<>(r, expr);
+ }
+ Triple<DatasetFullyQualifiedName, Boolean, DatasetFullyQualifiedName> dsArgs =
+ FunctionUtil.parseDatasetFunctionArguments(f);
+ if (!Boolean.TRUE.equals(dsArgs.second)) {
+ // not a view
+ return new Pair<>(r, expr);
+ }
+ DatasetFullyQualifiedName viewName = dsArgs.first;
+ ViewDecl implem = usedViews.get(viewName);
+ if (implem == null) {
+ throw new CompilationException(ErrorCode.UNKNOWN_VIEW, f.getSourceLocation(), viewName);
+ }
+ // it's one of the views we want to inline
+ letClauses = Collections.emptyList();
+ bodyVarSubst = new VariableSubstitutionEnvironment();
+ normBodyExpr = implem.getNormalizedViewBody();
+ if (normBodyExpr == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, f.getSourceLocation(),
+ viewName.toString());
+ }
+ } else {
+ FunctionDecl implem = usedUDFs.get(fs);
+ if (implem == null) {
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, f.getSourceLocation(), fs.toString());
+ }
+ // it's one of the functions we want to inline
+ boolean isVarargs = implem.getSignature().getArity() == FunctionIdentifier.VARARGS;
+ Pair<List<LetClause>, VariableSubstitutionEnvironment> clausesAndSubst =
+ createFunctionParametersSubstitution(implem.getParamList(), isVarargs, f.getExprList(),
+ f.getSourceLocation());
+ letClauses = clausesAndSubst.first;
+ bodyVarSubst = clausesAndSubst.second;
+ normBodyExpr = implem.getNormalizedFuncBody();
+ if (normBodyExpr == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, f.getSourceLocation(),
+ fs.toString());
+ }
}
+
if (f.hasAggregateFilterExpr()) {
throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_USE_OF_FILTER_CLAUSE, f.getSourceLocation());
}
- FunctionDecl implem = usedUDFs.get(fs);
- if (implem == null) {
- throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, f.getSourceLocation(), fs.toString());
- }
- // it's one of the functions we want to inline
- List<Expression> argList = f.getExprList();
+
+ Pair<ILangExpression, VariableSubstitutionEnvironment> p2 = normBodyExpr.accept(cloneVisitor, bodyVarSubst);
+ Expression resExpr = letClauses.isEmpty() ? (Expression) p2.first
+ : generateQueryExpression(letClauses, (Expression) p2.first);
+ return new Pair<>(true, resExpr);
+ }
+
+ private Pair<List<LetClause>, VariableSubstitutionEnvironment> createFunctionParametersSubstitution(
+ List<VarIdentifier> paramList, boolean isVarargs, List<Expression> argList, SourceLocation sourceLoc)
+ throws CompilationException {
int argCount = argList.size();
List<LetClause> clauses = new ArrayList<>(argCount + 1);
List<Expression> argVars = new ArrayList<>(argCount);
- for (Expression e : f.getExprList()) {
+ for (Expression e : argList) {
// Obs: we could do smth about passing also literals, or let
// variable inlining to take care of this.
VarIdentifier argVar;
if (e.getKind() == Kind.VARIABLE_EXPRESSION) {
argVar = ((VariableExpr) e).getVar();
} else {
- SourceLocation sourceLoc = e.getSourceLocation();
+ SourceLocation argSourceLoc = e.getSourceLocation();
argVar = context.newVariable();
Pair<ILangExpression, VariableSubstitutionEnvironment> p1 =
e.accept(cloneVisitor, new VariableSubstitutionEnvironment());
VariableExpr newVRef1 = new VariableExpr(argVar);
- newVRef1.setSourceLocation(sourceLoc);
+ newVRef1.setSourceLocation(argSourceLoc);
LetClause c = new LetClause(newVRef1, (Expression) p1.first);
- c.setSourceLocation(sourceLoc);
+ c.setSourceLocation(argSourceLoc);
clauses.add(c);
}
@@ -323,49 +372,34 @@
}
VariableSubstitutionEnvironment subst = new VariableSubstitutionEnvironment();
- List<VarIdentifier> paramList = implem.getParamList();
- if (implem.getSignature().getArity() == FunctionIdentifier.VARARGS) {
+ if (isVarargs) {
if (paramList.size() != 1) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expr.getSourceLocation(),
- paramList.size());
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, paramList.size());
}
VarIdentifier paramVarargs = paramList.get(0);
CallExpr argsListExpr =
new CallExpr(new FunctionSignature(BuiltinFunctions.ORDERED_LIST_CONSTRUCTOR), argVars);
- argsListExpr.setSourceLocation(expr.getSourceLocation());
+ argsListExpr.setSourceLocation(sourceLoc);
VarIdentifier argsVar = context.newVariable();
VariableExpr argsVarRef1 = new VariableExpr(argsVar);
- argsVarRef1.setSourceLocation(expr.getSourceLocation());
+ argsVarRef1.setSourceLocation(sourceLoc);
LetClause c = new LetClause(argsVarRef1, argsListExpr);
- c.setSourceLocation(expr.getSourceLocation());
+ c.setSourceLocation(sourceLoc);
clauses.add(c);
VariableExpr argsVarRef2 = new VariableExpr(argsVar);
- argsVarRef2.setSourceLocation(expr.getSourceLocation());
+ argsVarRef2.setSourceLocation(sourceLoc);
subst.addSubstituion(new VariableExpr(paramVarargs), argsVarRef2);
} else {
if (paramList.size() != argCount) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expr.getSourceLocation(),
- paramList.size());
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, paramList.size());
}
for (int i = 0; i < argCount; i++) {
subst.addSubstituion(new VariableExpr(paramList.get(i)), argVars.get(i));
}
}
-
- Expression funcBodyNorm = implem.getNormalizedFuncBody();
- if (funcBodyNorm == null) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, f.getSourceLocation(), fs.toString());
- }
- Pair<ILangExpression, VariableSubstitutionEnvironment> p2 = funcBodyNorm.accept(cloneVisitor, subst);
- Expression resExpr;
- if (clauses.isEmpty()) {
- resExpr = (Expression) p2.first;
- } else {
- resExpr = generateQueryExpression(clauses, (Expression) p2.first);
- }
- return new Pair<>(true, resExpr);
+ return new Pair<>(clauses, subst);
}
protected Pair<Boolean, List<Expression>> inlineUdfsInExprList(List<Expression> exprList)
@@ -373,7 +407,7 @@
List<Expression> newList = new ArrayList<>(exprList.size());
boolean changed = false;
for (Expression e : exprList) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(e);
+ Pair<Boolean, Expression> be = inlineUdfsAndViewsInExpr(e);
newList.add(be.second);
changed |= be.first;
}
@@ -385,7 +419,7 @@
List<GbyVariableExpressionPair> newList = new ArrayList<>(gbyPairList.size());
boolean changed = false;
for (GbyVariableExpressionPair p : gbyPairList) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr());
+ Pair<Boolean, Expression> be = inlineUdfsAndViewsInExpr(p.getExpr());
newList.add(new GbyVariableExpressionPair(p.getVar(), be.second));
changed |= be.first;
}
@@ -397,7 +431,7 @@
List<Pair<Expression, Identifier>> newList = new ArrayList<>(fieldList.size());
boolean changed = false;
for (Pair<Expression, Identifier> p : fieldList) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(p.first);
+ Pair<Boolean, Expression> be = inlineUdfsAndViewsInExpr(p.first);
newList.add(new Pair<>(be.second, p.second));
changed |= be.first;
}
@@ -409,7 +443,7 @@
Map<Expression, VariableExpr> newMap = new HashMap<>();
boolean changed = false;
for (Map.Entry<Expression, VariableExpr> me : varMap.entrySet()) {
- Pair<Boolean, Expression> be = inlineUdfsInExpr(me.getKey());
+ Pair<Boolean, Expression> be = inlineUdfsAndViewsInExpr(me.getKey());
newMap.put(be.second, me.getValue());
changed |= be.first;
}
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 2650ca3..12a1bd3 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
@@ -76,6 +76,7 @@
import org.apache.asterix.lang.common.statement.CreateIndexStatement;
import org.apache.asterix.lang.common.statement.CreateLibraryStatement;
import org.apache.asterix.lang.common.statement.CreateSynonymStatement;
+import org.apache.asterix.lang.common.statement.CreateViewStatement;
import org.apache.asterix.lang.common.statement.DatasetDecl;
import org.apache.asterix.lang.common.statement.DataverseDecl;
import org.apache.asterix.lang.common.statement.DataverseDropStatement;
@@ -104,6 +105,8 @@
import org.apache.asterix.lang.common.statement.TypeDecl;
import org.apache.asterix.lang.common.statement.TypeDropStatement;
import org.apache.asterix.lang.common.statement.UpdateStatement;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.lang.common.statement.ViewDropStatement;
import org.apache.asterix.lang.common.statement.WriteStatement;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.OperatorType;
@@ -957,6 +960,32 @@
return null;
}
+ @Override
+ public Void visit(CreateViewStatement cvs, Integer step) throws CompilationException {
+ out.print(skip(step) + CREATE + generateOrReplace(cvs.getReplaceIfExists()) + " view ");
+ out.print(generateIfNotExists(cvs.getIfNotExists()));
+ out.print(generateFullName(cvs.getDataverseName(), cvs.getViewName()));
+ out.print(" as ");
+ out.print(cvs.getViewBody());
+ out.println(SEMICOLON);
+ return null;
+ }
+
+ @Override
+ public Void visit(ViewDropStatement vds, Integer step) throws CompilationException {
+ out.print(skip(step) + "drop view ");
+ out.print(generateFullName(vds.getDataverseName(), vds.getViewName()));
+ out.print(generateIfExists(vds.getIfExists()));
+ out.println(SEMICOLON);
+ return null;
+ }
+
+ @Override
+ public Void visit(ViewDecl vd, Integer arg) throws CompilationException {
+ // this statement is internal
+ return null;
+ }
+
protected void printConfiguration(Map<String, String> properties) {
if (properties.size() > 0) {
out.print("(");
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
index 25f4103..b7cf7af 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
@@ -47,7 +47,6 @@
import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
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.Identifier;
@@ -242,9 +241,4 @@
}
return null;
}
-
- @Override
- public Void visit(FunctionDecl fd, Void arg) throws CompilationException {
- return null;
- }
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
index 0b4f56b..91fe664 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
@@ -37,6 +37,7 @@
import org.apache.asterix.lang.common.statement.CreateIndexStatement;
import org.apache.asterix.lang.common.statement.CreateLibraryStatement;
import org.apache.asterix.lang.common.statement.CreateSynonymStatement;
+import org.apache.asterix.lang.common.statement.CreateViewStatement;
import org.apache.asterix.lang.common.statement.DatasetDecl;
import org.apache.asterix.lang.common.statement.DataverseDecl;
import org.apache.asterix.lang.common.statement.DataverseDropStatement;
@@ -63,6 +64,8 @@
import org.apache.asterix.lang.common.statement.TypeDecl;
import org.apache.asterix.lang.common.statement.TypeDropStatement;
import org.apache.asterix.lang.common.statement.UpdateStatement;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.lang.common.statement.ViewDropStatement;
import org.apache.asterix.lang.common.statement.WriteStatement;
public abstract class AbstractQueryExpressionVisitor<R, T> implements ILangVisitor<R, T> {
@@ -291,4 +294,19 @@
public R visit(LibraryDropStatement del, T arg) throws CompilationException {
return null;
}
+
+ @Override
+ public R visit(CreateViewStatement cvs, T arg) throws CompilationException {
+ return null;
+ }
+
+ @Override
+ public R visit(ViewDropStatement vds, T arg) throws CompilationException {
+ return null;
+ }
+
+ @Override
+ public R visit(ViewDecl vd, T arg) throws CompilationException {
+ return null;
+ }
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java
index e36ec73..c2b1311 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/ILangVisitor.java
@@ -54,6 +54,7 @@
import org.apache.asterix.lang.common.statement.CreateIndexStatement;
import org.apache.asterix.lang.common.statement.CreateLibraryStatement;
import org.apache.asterix.lang.common.statement.CreateSynonymStatement;
+import org.apache.asterix.lang.common.statement.CreateViewStatement;
import org.apache.asterix.lang.common.statement.DatasetDecl;
import org.apache.asterix.lang.common.statement.DataverseDecl;
import org.apache.asterix.lang.common.statement.DataverseDropStatement;
@@ -80,6 +81,8 @@
import org.apache.asterix.lang.common.statement.TypeDecl;
import org.apache.asterix.lang.common.statement.TypeDropStatement;
import org.apache.asterix.lang.common.statement.UpdateStatement;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.lang.common.statement.ViewDropStatement;
import org.apache.asterix.lang.common.statement.WriteStatement;
public interface ILangVisitor<R, T> {
@@ -207,4 +210,10 @@
R visit(CompactStatement del, T arg) throws CompilationException;
R visit(ListSliceExpression expression, T arg) throws CompilationException;
+
+ R visit(CreateViewStatement cvs, T arg) throws CompilationException;
+
+ R visit(ViewDropStatement vds, T arg) throws CompilationException;
+
+ R visit(ViewDecl vd, T arg) throws CompilationException;
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
index 8dd206f..6287d2e 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
@@ -27,6 +27,9 @@
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.struct.VarIdentifier;
+/**
+ * This rewriter is used to rewrite body expression of user defined functions and views
+ */
class SqlppFunctionBodyRewriter extends SqlppQueryRewriter {
public SqlppFunctionBodyRewriter(IParserFactory parserFactory) {
@@ -35,15 +38,15 @@
@Override
public void rewrite(LangRewritingContext context, IReturningStatement topStatement, boolean allowNonStoredUdfCalls,
- boolean inlineUdfs, Collection<VarIdentifier> externalVars) throws CompilationException {
- if (inlineUdfs) {
- // When rewriting function body we do not inline UDFs into it.
+ boolean inlineUdfsAndViews, Collection<VarIdentifier> externalVars) throws CompilationException {
+ if (inlineUdfsAndViews) {
+ // When rewriting function or view body we do not inline UDFs or views into it.
// The main query rewriter will inline everything later, when it processes the query
- throw new CompilationException(ErrorCode.ILLEGAL_STATE, topStatement.getSourceLocation(), "inlineUdfs");
+ throw new CompilationException(ErrorCode.ILLEGAL_STATE, topStatement.getSourceLocation(), "");
}
// Sets up parameters.
- setup(context, topStatement, externalVars, allowNonStoredUdfCalls, inlineUdfs);
+ setup(context, topStatement, externalVars, allowNonStoredUdfCalls, inlineUdfsAndViews);
// Resolves function calls
resolveFunctionCalls();
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriterFactory.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriterFactory.java
deleted file mode 100644
index bf27464..0000000
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriterFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.lang.sqlpp.rewrites;
-
-import org.apache.asterix.lang.common.base.IParserFactory;
-import org.apache.asterix.lang.common.base.IQueryRewriter;
-import org.apache.asterix.lang.common.base.IRewriterFactory;
-import org.apache.asterix.lang.common.base.IStatementRewriter;
-
-class SqlppFunctionBodyRewriterFactory implements IRewriterFactory {
-
- private final IParserFactory parserFactory;
-
- public SqlppFunctionBodyRewriterFactory(IParserFactory parserFactory) {
- this.parserFactory = parserFactory;
- }
-
- @Override
- public IQueryRewriter createQueryRewriter() {
- return new SqlppFunctionBodyRewriter(parserFactory);
- }
-
- @Override
- public IStatementRewriter createStatementRewriter() {
- throw new IllegalStateException("There could not be non-query statements inside a function definition.");
- }
-
-}
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 a3ff1c6..f07e614 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
@@ -24,24 +24,35 @@
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
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.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.lang.common.base.AbstractExpression;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.IParserFactory;
import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.base.IReturningStatement;
import org.apache.asterix.lang.common.expression.AbstractCallExpression;
+import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.FieldAccessor;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.literal.MissingLiteral;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.statement.FunctionDecl;
import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.common.util.ExpressionUtils;
import org.apache.asterix.lang.common.util.FunctionUtil;
+import org.apache.asterix.lang.common.util.ViewUtil;
import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.GenerateColumnNameVisitor;
import org.apache.asterix.lang.sqlpp.rewrites.visitor.InlineColumnAliasVisitor;
@@ -66,9 +77,16 @@
import org.apache.asterix.lang.sqlpp.util.SqlppAstPrintUtil;
import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.metadata.entities.Dataset;
import org.apache.asterix.metadata.entities.Dataverse;
import org.apache.asterix.metadata.entities.Function;
+import org.apache.asterix.metadata.entities.ViewDetails;
+import org.apache.asterix.metadata.utils.DatasetUtil;
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;
import org.apache.hyracks.util.LogRedactionUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -80,13 +98,13 @@
public static final String INLINE_WITH_OPTION = "inline_with";
private static final boolean INLINE_WITH_OPTION_DEFAULT = true;
private final IParserFactory parserFactory;
- private SqlppFunctionBodyRewriter functionBodyRewriter;
+ private SqlppFunctionBodyRewriter functionAndViewBodyRewriter;
private IReturningStatement topStatement;
private LangRewritingContext context;
private MetadataProvider metadataProvider;
private Collection<VarIdentifier> externalVars;
private boolean allowNonStoredUdfCalls;
- private boolean inlineUdfs;
+ private boolean inlineUdfsAndViews;
private boolean isLogEnabled;
public SqlppQueryRewriter(IParserFactory parserFactory) {
@@ -94,24 +112,24 @@
}
protected void setup(LangRewritingContext context, IReturningStatement topStatement,
- Collection<VarIdentifier> externalVars, boolean allowNonStoredUdfCalls, boolean inlineUdfs)
+ Collection<VarIdentifier> externalVars, boolean allowNonStoredUdfCalls, boolean inlineUdfsAndViews)
throws CompilationException {
this.context = context;
this.metadataProvider = context.getMetadataProvider();
this.topStatement = topStatement;
this.externalVars = externalVars != null ? externalVars : Collections.emptyList();
this.allowNonStoredUdfCalls = allowNonStoredUdfCalls;
- this.inlineUdfs = inlineUdfs;
+ this.inlineUdfsAndViews = inlineUdfsAndViews;
this.isLogEnabled = LOGGER.isTraceEnabled();
logExpression("Starting AST rewrites on", "");
}
@Override
public void rewrite(LangRewritingContext context, IReturningStatement topStatement, boolean allowNonStoredUdfCalls,
- boolean inlineUdfs, Collection<VarIdentifier> externalVars) throws CompilationException {
+ boolean inlineUdfsAndViews, Collection<VarIdentifier> externalVars) throws CompilationException {
// Sets up parameters.
- setup(context, topStatement, externalVars, allowNonStoredUdfCalls, inlineUdfs);
+ setup(context, topStatement, externalVars, allowNonStoredUdfCalls, inlineUdfsAndViews);
// Resolves function calls
resolveFunctionCalls();
@@ -162,8 +180,8 @@
// Rewrites RIGHT OUTER JOINs into LEFT OUTER JOINs if possible
rewriteRightJoins();
- // Inlines functions.
- loadAndInlineDeclaredUdfs();
+ // Inlines functions and views
+ loadAndInlineUdfsAndViews();
// Rewrites SQL++ core aggregate function names into internal names
rewriteSpecialFunctionNames();
@@ -289,12 +307,21 @@
rewriteTopExpr(visitor, null);
}
- protected void loadAndInlineDeclaredUdfs() throws CompilationException {
- Map<FunctionSignature, FunctionDecl> udfs = fetchUserDefinedSqlppFunctions(topStatement);
- FunctionUtil.checkFunctionRecursion(udfs, SqlppGatherFunctionCallsVisitor::new,
- topStatement.getSourceLocation());
- if (!udfs.isEmpty() && inlineUdfs) {
- SqlppInlineUdfsVisitor visitor = new SqlppInlineUdfsVisitor(context, udfs);
+ protected void loadAndInlineUdfsAndViews() throws CompilationException {
+ Pair<Map<FunctionSignature, FunctionDecl>, Map<DatasetFullyQualifiedName, ViewDecl>> udfAndViewDecls =
+ loadUdfsAndViews(topStatement);
+ Map<FunctionSignature, FunctionDecl> udfs = udfAndViewDecls.first;
+ Map<DatasetFullyQualifiedName, ViewDecl> views = udfAndViewDecls.second;
+ if (udfs.isEmpty() && views.isEmpty()) {
+ // nothing to do
+ return;
+ }
+ if (ExpressionUtils.hasFunctionOrViewRecursion(udfs, views, SqlppGatherFunctionCallsVisitor::new)) {
+ throw new CompilationException(ErrorCode.ILLEGAL_FUNCTION_OR_VIEW_RECURSION,
+ topStatement.getSourceLocation());
+ }
+ if (inlineUdfsAndViews) {
+ SqlppInlineUdfsVisitor visitor = new SqlppInlineUdfsVisitor(context, udfs, views);
while (rewriteTopExpr(visitor, null)) {
// loop until no more changes
}
@@ -332,14 +359,24 @@
return extVars;
}
- private Map<FunctionSignature, FunctionDecl> fetchUserDefinedSqlppFunctions(IReturningStatement topExpr)
- throws CompilationException {
- Map<FunctionSignature, FunctionDecl> udfs = new LinkedHashMap<>();
+ @Override
+ public VarIdentifier toExternalVariableName(String statementParameterName) {
+ return SqlppVariableUtil.toExternalVariableIdentifier(statementParameterName);
+ }
+ @Override
+ public String toFunctionParameterName(VarIdentifier paramVar) {
+ return SqlppVariableUtil.toUserDefinedName(paramVar.getValue());
+ }
+
+ private Pair<Map<FunctionSignature, FunctionDecl>, Map<DatasetFullyQualifiedName, ViewDecl>> loadUdfsAndViews(
+ IReturningStatement topExpr) throws CompilationException {
+ Map<FunctionSignature, FunctionDecl> udfs = new LinkedHashMap<>();
+ Map<DatasetFullyQualifiedName, ViewDecl> views = new LinkedHashMap<>();
Deque<AbstractCallExpression> workQueue = new ArrayDeque<>();
- SqlppGatherFunctionCallsVisitor gfc = new SqlppGatherFunctionCallsVisitor(workQueue);
+ SqlppGatherFunctionCallsVisitor callVisitor = new SqlppGatherFunctionCallsVisitor(workQueue);
for (Expression expr : topExpr.getDirectlyEnclosedExpressions()) {
- expr.accept(gfc, null);
+ expr.accept(callVisitor, null);
}
AbstractCallExpression fnCall;
while ((fnCall = workQueue.poll()) != null) {
@@ -351,31 +388,30 @@
throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, fnCall.getSourceLocation(),
fs);
}
- if (FunctionUtil.isBuiltinFunctionSignature(fs) || udfs.containsKey(fs)) {
- continue;
+ if (FunctionUtil.isBuiltinFunctionSignature(fs)) {
+ if (FunctionUtil.isBuiltinDatasetFunction(fs)) {
+ Triple<DatasetFullyQualifiedName, Boolean, DatasetFullyQualifiedName> dsArgs =
+ FunctionUtil.parseDatasetFunctionArguments(fnCall);
+ if (Boolean.TRUE.equals(dsArgs.second)) {
+ DatasetFullyQualifiedName viewName = dsArgs.first;
+ if (!views.containsKey(viewName)) {
+ ViewDecl viewDecl = fetchViewDecl(viewName, fnCall.getSourceLocation());
+ if (viewDecl != null) {
+ views.put(viewName, viewDecl);
+ viewDecl.getNormalizedViewBody().accept(callVisitor, null);
+ }
+ }
+ }
+ }
+ } else {
+ if (!udfs.containsKey(fs)) {
+ FunctionDecl fd = fetchFunctionDecl(fs, fnCall.getSourceLocation());
+ if (fd != null) {
+ udfs.put(fs, fd);
+ fd.getNormalizedFuncBody().accept(callVisitor, null);
+ }
+ }
}
- FunctionDecl fd = context.getDeclaredFunctions().get(fs);
- if (fd == null) {
- Function function;
- try {
- function = metadataProvider.lookupUserDefinedFunction(fs);
- } catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, fnCall.getSourceLocation(),
- fs.toString());
- }
- if (function == null) {
- throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, fnCall.getSourceLocation(),
- fs.toString());
- }
- if (function.isExternal()) {
- continue;
- }
- fd = FunctionUtil.parseStoredFunction(function, parserFactory, context.getWarningCollector(),
- fnCall.getSourceLocation());
- }
- prepareFunction(fd);
- udfs.put(fs, fd);
- fd.getNormalizedFuncBody().accept(gfc, null);
break;
case WINDOW_EXPRESSION:
// there cannot be used-defined window functions
@@ -385,54 +421,145 @@
fnCall.getFunctionSignature().toString(false));
}
}
- return udfs;
+ return new Pair<>(udfs, views);
}
- private void prepareFunction(FunctionDecl fd) throws CompilationException {
- Expression fnNormBody = fd.getNormalizedFuncBody();
- if (fnNormBody == null) {
- fnNormBody = rewriteFunctionBody(fd);
- fd.setNormalizedFuncBody(fnNormBody);
+ private FunctionDecl fetchFunctionDecl(FunctionSignature fs, SourceLocation sourceLoc) throws CompilationException {
+ FunctionDecl fd = context.getDeclaredFunctions().get(fs);
+ if (fd == null) {
+ Function function;
+ try {
+ function = metadataProvider.lookupUserDefinedFunction(fs);
+ } catch (AlgebricksException e) {
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, sourceLoc, fs.toString());
+ }
+ if (function == null) {
+ throw new CompilationException(ErrorCode.UNKNOWN_FUNCTION, sourceLoc, fs.toString());
+ }
+ if (function.isExternal()) {
+ return null;
+ }
+ fd = FunctionUtil.parseStoredFunction(function, parserFactory, context.getWarningCollector(), sourceLoc);
}
+ Expression normBody = fd.getNormalizedFuncBody();
+ if (normBody == null) {
+ normBody = rewriteFunctionBody(fd);
+ fd.setNormalizedFuncBody(normBody);
+ }
+ return fd;
+ }
+
+ private ViewDecl fetchViewDecl(DatasetFullyQualifiedName viewName, SourceLocation sourceLoc)
+ throws CompilationException {
+ ViewDecl viewDecl = context.getDeclaredViews().get(viewName);
+ if (viewDecl == null) {
+ Dataset dataset;
+ try {
+ dataset = metadataProvider.findDataset(viewName.getDataverseName(), viewName.getDatasetName(), true);
+ } catch (AlgebricksException e) {
+ throw new CompilationException(ErrorCode.UNKNOWN_VIEW, e, sourceLoc, viewName);
+ }
+ if (dataset == null || DatasetUtil.isNotView(dataset)) {
+ throw new CompilationException(ErrorCode.UNKNOWN_VIEW, sourceLoc, viewName);
+ }
+ ViewDetails viewDetails = (ViewDetails) dataset.getDatasetDetails();
+ viewDecl = ViewUtil.parseStoredView(viewName, viewDetails, parserFactory, context.getWarningCollector(),
+ sourceLoc);
+ }
+ Expression normBody = viewDecl.getNormalizedViewBody();
+ if (normBody == null) {
+ normBody = rewriteViewBody(viewDecl);
+ viewDecl.setNormalizedViewBody(normBody);
+ }
+ return viewDecl;
}
private Expression rewriteFunctionBody(FunctionDecl fnDecl) throws CompilationException {
- DataverseName fnDataverseName = fnDecl.getSignature().getDataverseName();
+ FunctionSignature fs = fnDecl.getSignature();
+ return rewriteFunctionOrViewBody(fs.getDataverseName(), fs, fnDecl.getFuncBody(), fnDecl.getParamList(),
+ !fnDecl.isStored(), fnDecl.getSourceLocation());
+ }
+
+ private Expression rewriteViewBody(ViewDecl viewDecl) throws CompilationException {
+ DatasetFullyQualifiedName viewName = viewDecl.getViewName();
+ return rewriteFunctionOrViewBody(viewName.getDataverseName(), viewName, viewDecl.getViewBody(),
+ Collections.emptyList(), false, viewDecl.getSourceLocation());
+ }
+
+ private Expression rewriteFunctionOrViewBody(DataverseName entityDataverseName, Object entityDisplayName,
+ Expression bodyExpr, List<VarIdentifier> externalVars, boolean allowNonStoredUdfCalls,
+ SourceLocation sourceLoc) throws CompilationException {
Dataverse defaultDataverse = metadataProvider.getDefaultDataverse();
- Dataverse fnDataverse;
- if (fnDataverseName == null || fnDataverseName.equals(defaultDataverse.getDataverseName())) {
- fnDataverse = defaultDataverse;
+ Dataverse targetDataverse;
+ if (entityDataverseName == null || entityDataverseName.equals(defaultDataverse.getDataverseName())) {
+ targetDataverse = defaultDataverse;
} else {
try {
- fnDataverse = metadataProvider.findDataverse(fnDataverseName);
+ targetDataverse = metadataProvider.findDataverse(entityDataverseName);
} catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, e, fnDecl.getSourceLocation(),
- fnDataverseName);
+ throw new CompilationException(ErrorCode.UNKNOWN_DATAVERSE, e, sourceLoc, entityDataverseName);
}
}
- metadataProvider.setDefaultDataverse(fnDataverse);
+ metadataProvider.setDefaultDataverse(targetDataverse);
try {
- Query wrappedQuery = new Query(false);
- wrappedQuery.setSourceLocation(fnDecl.getSourceLocation());
- wrappedQuery.setBody(fnDecl.getFuncBody());
- wrappedQuery.setTopLevel(false);
- boolean allowNonStoredUdfCalls = !fnDecl.isStored();
- getFunctionBodyRewriter().rewrite(context, wrappedQuery, allowNonStoredUdfCalls, false,
- fnDecl.getParamList());
+ Query wrappedQuery = createWrappedQuery(bodyExpr, sourceLoc);
+ getFunctionAndViewBodyRewriter().rewrite(context, wrappedQuery, allowNonStoredUdfCalls, false,
+ externalVars);
return wrappedQuery.getBody();
} catch (CompilationException e) {
- throw new CompilationException(ErrorCode.COMPILATION_BAD_FUNCTION_DEFINITION, e, fnDecl.getSignature(),
- e.getMessage());
+ throw new CompilationException(ErrorCode.COMPILATION_BAD_FUNCTION_DEFINITION, e,
+ entityDisplayName.toString(), e.getMessage());
} finally {
metadataProvider.setDefaultDataverse(defaultDataverse);
}
}
- protected SqlppFunctionBodyRewriter getFunctionBodyRewriter() {
- if (functionBodyRewriter == null) {
- functionBodyRewriter = new SqlppFunctionBodyRewriter(parserFactory);
+ protected SqlppFunctionBodyRewriter getFunctionAndViewBodyRewriter() {
+ if (functionAndViewBodyRewriter == null) {
+ functionAndViewBodyRewriter = new SqlppFunctionBodyRewriter(parserFactory);
}
- return functionBodyRewriter;
+ return functionAndViewBodyRewriter;
+ }
+
+ @Override
+ public Query createFunctionAccessorQuery(FunctionDecl functionDecl) {
+ // dataverse_name.function_name(MISSING, ... MISSING)
+ FunctionSignature functionSignature = functionDecl.getSignature();
+ int arity = functionSignature.getArity();
+ List<Expression> args = arity == FunctionIdentifier.VARARGS ? Collections.emptyList()
+ : Collections.nCopies(arity, new LiteralExpr(MissingLiteral.INSTANCE));
+ CallExpr fcall = new CallExpr(functionSignature, args);
+ fcall.setSourceLocation(functionDecl.getSourceLocation());
+
+ return createWrappedQuery(fcall, functionDecl.getSourceLocation());
+ }
+
+ @Override
+ public Query createViewAccessorQuery(ViewDecl viewDecl) {
+ // dataverse_name.view_name
+ DataverseName dataverseName = viewDecl.getViewName().getDataverseName();
+ String viewName = viewDecl.getViewName().getDatasetName();
+ SourceLocation sourceLoc = viewDecl.getSourceLocation();
+ List<String> dataverseNameParts = dataverseName.getParts();
+ AbstractExpression vAccessExpr = null;
+ for (int i = 0, n = dataverseNameParts.size(); i < n; i++) {
+ String part = dataverseNameParts.get(i);
+ vAccessExpr = i == 0 ? new VariableExpr(new VarIdentifier(SqlppVariableUtil.toInternalVariableName(part)))
+ : new FieldAccessor(vAccessExpr, new Identifier(part));
+ vAccessExpr.setSourceLocation(sourceLoc);
+ }
+ vAccessExpr = new FieldAccessor(vAccessExpr, new Identifier(viewName));
+ vAccessExpr.setSourceLocation(sourceLoc);
+
+ return createWrappedQuery(vAccessExpr, viewDecl.getSourceLocation());
+ }
+
+ private static Query createWrappedQuery(Expression expr, SourceLocation sourceLoc) {
+ Query wrappedQuery = new Query(false);
+ wrappedQuery.setSourceLocation(sourceLoc);
+ wrappedQuery.setBody(expr);
+ wrappedQuery.setTopLevel(false);
+ return wrappedQuery;
}
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java
index a9caacb..f9b0e7a 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppStatementRewriter.java
@@ -21,8 +21,6 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.lang.common.base.IStatementRewriter;
import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.lang.common.struct.VarIdentifier;
-import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
import org.apache.asterix.lang.sqlpp.visitor.SqlppDeleteRewriteVisitor;
import org.apache.asterix.lang.sqlpp.visitor.SqlppSynonymRewriteVisitor;
import org.apache.asterix.metadata.declared.MetadataProvider;
@@ -49,14 +47,4 @@
stmt.accept(SqlppDeleteRewriteVisitor.INSTANCE, metadataProvider);
}
}
-
- @Override
- public String toExternalVariableName(String statementParameterName) {
- return SqlppVariableUtil.toExternalVariableName(statementParameterName);
- }
-
- @Override
- public String toFunctionParameterName(VarIdentifier paramVar) {
- return SqlppVariableUtil.toUserDefinedName(paramVar.getValue());
- }
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
index 5200b94..56fdd19 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
@@ -24,12 +24,14 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.lang.common.base.AbstractClause;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.clause.LetClause;
import org.apache.asterix.lang.common.expression.ListSliceExpression;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.ViewDecl;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.visitor.AbstractInlineUdfsVisitor;
import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
@@ -61,9 +63,12 @@
* manages ids of variables and guarantees uniqueness of variables.
* @param usedUDFs,
* user defined functions used by this query.
+ * @param usedViews,
+ * views used by this query.
*/
- public SqlppInlineUdfsVisitor(LangRewritingContext context, Map<FunctionSignature, FunctionDecl> usedUDFs) {
- super(context, usedUDFs, new SqlppCloneAndSubstituteVariablesVisitor(context));
+ public SqlppInlineUdfsVisitor(LangRewritingContext context, Map<FunctionSignature, FunctionDecl> usedUDFs,
+ Map<DatasetFullyQualifiedName, ViewDecl> usedViews) {
+ super(context, usedUDFs, usedViews, new SqlppCloneAndSubstituteVariablesVisitor(context));
}
@Override
@@ -85,7 +90,7 @@
@Override
public Boolean visit(FromTerm fromTerm, Void arg) throws CompilationException {
boolean changed = false;
- Pair<Boolean, Expression> p = inlineUdfsInExpr(fromTerm.getLeftExpression());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(fromTerm.getLeftExpression());
fromTerm.setLeftExpression(p.second);
changed |= p.first;
for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
@@ -96,18 +101,18 @@
@Override
public Boolean visit(JoinClause joinClause, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(joinClause.getRightExpression());
+ Pair<Boolean, Expression> p1 = inlineUdfsAndViewsInExpr(joinClause.getRightExpression());
joinClause.setRightExpression(p1.second);
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(joinClause.getConditionExpression());
+ Pair<Boolean, Expression> p2 = inlineUdfsAndViewsInExpr(joinClause.getConditionExpression());
joinClause.setConditionExpression(p2.second);
return p1.first || p2.first;
}
@Override
public Boolean visit(NestClause nestClause, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p1 = inlineUdfsInExpr(nestClause.getRightExpression());
+ Pair<Boolean, Expression> p1 = inlineUdfsAndViewsInExpr(nestClause.getRightExpression());
nestClause.setRightExpression(p1.second);
- Pair<Boolean, Expression> p2 = inlineUdfsInExpr(nestClause.getConditionExpression());
+ Pair<Boolean, Expression> p2 = inlineUdfsAndViewsInExpr(nestClause.getConditionExpression());
nestClause.setConditionExpression(p2.second);
return p1.first || p2.first;
}
@@ -117,7 +122,7 @@
if (projection.star()) {
return false;
}
- Pair<Boolean, Expression> p = inlineUdfsInExpr(projection.getExpression());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(projection.getExpression());
projection.setExpression(p.second);
return p.first;
}
@@ -158,7 +163,7 @@
@Override
public Boolean visit(SelectElement selectElement, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(selectElement.getExpression());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(selectElement.getExpression());
selectElement.setExpression(p.second);
return p.first;
}
@@ -202,21 +207,21 @@
@Override
public Boolean visit(UnnestClause unnestClause, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(unnestClause.getRightExpression());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(unnestClause.getRightExpression());
unnestClause.setRightExpression(p.second);
return p.first;
}
@Override
public Boolean visit(HavingClause havingClause, Void arg) throws CompilationException {
- Pair<Boolean, Expression> p = inlineUdfsInExpr(havingClause.getFilterExpression());
+ Pair<Boolean, Expression> p = inlineUdfsAndViewsInExpr(havingClause.getFilterExpression());
havingClause.setFilterExpression(p.second);
return p.first;
}
@Override
public Boolean visit(CaseExpression caseExpr, Void arg) throws CompilationException {
- Pair<Boolean, Expression> result = inlineUdfsInExpr(caseExpr.getConditionExpr());
+ Pair<Boolean, Expression> result = inlineUdfsAndViewsInExpr(caseExpr.getConditionExpr());
caseExpr.setConditionExpr(result.second);
boolean inlined = result.first;
@@ -228,7 +233,7 @@
inlined = inlined || inlinedList.first;
caseExpr.setThenExprs(inlinedList.second);
- result = inlineUdfsInExpr(caseExpr.getElseExpr());
+ result = inlineUdfsAndViewsInExpr(caseExpr.getElseExpr());
caseExpr.setElseExpr(result.second);
return inlined || result.first;
}
@@ -247,12 +252,12 @@
inlined |= inlinedList.first;
}
if (winExpr.hasFrameStartExpr()) {
- Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getFrameStartExpr());
+ Pair<Boolean, Expression> inlinedExpr = inlineUdfsAndViewsInExpr(winExpr.getFrameStartExpr());
winExpr.setFrameStartExpr(inlinedExpr.second);
inlined |= inlinedExpr.first;
}
if (winExpr.hasFrameEndExpr()) {
- Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getFrameEndExpr());
+ Pair<Boolean, Expression> inlinedExpr = inlineUdfsAndViewsInExpr(winExpr.getFrameEndExpr());
winExpr.setFrameEndExpr(inlinedExpr.second);
inlined |= inlinedExpr.first;
}
@@ -263,7 +268,7 @@
inlined |= inlinedList.first;
}
if (winExpr.hasAggregateFilterExpr()) {
- Pair<Boolean, Expression> inlinedExpr = inlineUdfsInExpr(winExpr.getAggregateFilterExpr());
+ Pair<Boolean, Expression> inlinedExpr = inlineUdfsAndViewsInExpr(winExpr.getAggregateFilterExpr());
winExpr.setAggregateFilterExpr(inlinedExpr.second);
inlined |= inlinedExpr.first;
}
@@ -275,17 +280,19 @@
@Override
public Boolean visit(ListSliceExpression expression, Void arg) throws CompilationException {
- Pair<Boolean, Expression> expressionResult = inlineUdfsInExpr(expression.getExpr());
+ Pair<Boolean, Expression> expressionResult = inlineUdfsAndViewsInExpr(expression.getExpr());
expression.setExpr(expressionResult.second);
boolean inlined = expressionResult.first;
- Pair<Boolean, Expression> startIndexExpressResult = inlineUdfsInExpr(expression.getStartIndexExpression());
+ Pair<Boolean, Expression> startIndexExpressResult =
+ inlineUdfsAndViewsInExpr(expression.getStartIndexExpression());
expression.setStartIndexExpression(startIndexExpressResult.second);
inlined |= startIndexExpressResult.first;
// End index expression can be null (optional)
if (expression.hasEndExpression()) {
- Pair<Boolean, Expression> endIndexExpressionResult = inlineUdfsInExpr(expression.getEndIndexExpression());
+ Pair<Boolean, Expression> endIndexExpressionResult =
+ inlineUdfsAndViewsInExpr(expression.getEndIndexExpression());
expression.setEndIndexExpression(endIndexExpressionResult.second);
inlined |= endIndexExpressionResult.first;
}
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 bbf1a46..4b0caca 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
@@ -25,10 +25,12 @@
import java.util.Map;
import java.util.Set;
+import org.apache.asterix.common.config.DatasetConfig;
import org.apache.asterix.common.exceptions.AsterixException;
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.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.Expression.Kind;
@@ -38,8 +40,11 @@
import org.apache.asterix.lang.common.expression.FieldAccessor;
import org.apache.asterix.lang.common.expression.LiteralExpr;
import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.literal.FalseLiteral;
import org.apache.asterix.lang.common.literal.StringLiteral;
+import org.apache.asterix.lang.common.literal.TrueLiteral;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.statement.ViewDecl;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
@@ -169,15 +174,30 @@
return null;
}
SourceLocation sourceLoc = varExpr.getSourceLocation();
- Pair<Dataset, Boolean> datasetSynonymPair = findDataset(dataverseName, datasetName, sourceLoc);
- if (datasetSynonymPair == null) {
- throw createUnresolvableError(dataverseName, datasetName, sourceLoc);
+ DataverseName resolvedDataverseName;
+ String resolvedDatasetName;
+ boolean viaSynonym, isView;
+ ViewDecl viewDecl = findDeclaredView(dataverseName, datasetName);
+ if (viewDecl != null) {
+ resolvedDataverseName = viewDecl.getViewName().getDataverseName();
+ resolvedDatasetName = viewDecl.getViewName().getDatasetName();
+ viaSynonym = false;
+ isView = true;
+ } else {
+ Pair<Dataset, Boolean> p = findDataset(dataverseName, datasetName, true, sourceLoc);
+ if (p == null) {
+ throw createUnresolvableError(dataverseName, datasetName, sourceLoc);
+ }
+ Dataset resolvedDataset = p.first;
+ resolvedDataverseName = resolvedDataset.getDataverseName();
+ resolvedDatasetName = resolvedDataset.getDatasetName();
+ viaSynonym = p.second;
+ isView = resolvedDataset.getDatasetType() == DatasetConfig.DatasetType.VIEW;
}
- 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())));
+ List<Expression> argList = new ArrayList<>(3 + (viaSynonym ? 2 : 0));
+ argList.add(new LiteralExpr(new StringLiteral(resolvedDataverseName.getCanonicalForm())));
+ argList.add(new LiteralExpr(new StringLiteral(resolvedDatasetName)));
+ argList.add(new LiteralExpr(isView ? TrueLiteral.INSTANCE : FalseLiteral.INSTANCE));
if (viaSynonym) {
argList.add(new LiteralExpr(new StringLiteral(dataverseName.getCanonicalForm())));
argList.add(new LiteralExpr(new StringLiteral(datasetName)));
@@ -241,24 +261,30 @@
dataverseName == null ? defaultDataverseName : dataverseName);
}
- private Pair<Dataset, Boolean> findDataset(DataverseName dataverseName, String datasetName,
+ private Pair<Dataset, Boolean> findDataset(DataverseName dataverseName, String datasetName, boolean includingViews,
SourceLocation sourceLoc) throws CompilationException {
try {
Boolean viaSynonym = false;
Triple<DataverseName, String, Boolean> dsName =
- metadataProvider.resolveDatasetNameUsingSynonyms(dataverseName, datasetName);
+ metadataProvider.resolveDatasetNameUsingSynonyms(dataverseName, datasetName, includingViews);
if (dsName != null) {
dataverseName = dsName.first;
datasetName = dsName.second;
viaSynonym = dsName.third;
}
- Dataset dataset = metadataProvider.findDataset(dataverseName, datasetName);
+ Dataset dataset = metadataProvider.findDataset(dataverseName, datasetName, includingViews);
return dataset == null ? null : new Pair<>(dataset, viaSynonym);
} catch (AlgebricksException e) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, sourceLoc, e.getMessage());
}
}
+ private ViewDecl findDeclaredView(DataverseName dataverseName, String viewName) {
+ Map<DatasetFullyQualifiedName, ViewDecl> declaredViews = context.getDeclaredViews();
+ return declaredViews.isEmpty() ? null
+ : declaredViews.get(new DatasetFullyQualifiedName(dataverseName, viewName));
+ }
+
@Override
public Expression visit(CallExpr callExpr, ILangExpression arg) throws CompilationException {
// skip variables inside SQL-92 aggregates (they will be resolved by SqlppGroupByAggregationSugarVisitor)
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
index 26f2a35..9d50160 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
@@ -103,6 +103,10 @@
return EXTERNAL_VAR_PREFIX + varName;
}
+ public static VarIdentifier toExternalVariableIdentifier(String idName) {
+ return new VarIdentifier(toExternalVariableName(idName));
+ }
+
public static boolean isPositionalVariableIdentifier(VarIdentifier varId) {
try {
Integer.parseInt(toUserDefinedName(varId.getValue()));
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 083015b..efb9446 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
@@ -22,10 +22,10 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.lang.common.base.AbstractClause;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.clause.GroupbyClause;
@@ -59,6 +59,7 @@
import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.common.utils.Triple;
public class SqlppAstPrintVisitor extends QueryPrintVisitor implements ISqlppVisitor<Void, Integer> {
@@ -252,8 +253,10 @@
FunctionSignature functionSignature = callExpr.getFunctionSignature();
//TODO(MULTI_PART_DATAVERSE_NAME):temporary workaround to preserve AST reference results
if (FunctionUtil.isBuiltinDatasetFunction(functionSignature)) {
- String singleArg = callExpr.getExprList().stream().map(LiteralExpr.class::cast).map(LiteralExpr::getValue)
- .map(StringLiteral.class::cast).map(StringLiteral::getValue).collect(Collectors.joining("."));
+ Triple<DatasetFullyQualifiedName, Boolean, DatasetFullyQualifiedName> dsArgs =
+ FunctionUtil.parseDatasetFunctionArguments(callExpr);
+ String singleArg =
+ String.join(".", dsArgs.first.getDataverseName().getParts()) + "." + dsArgs.first.getDatasetName();
printFunctionCall(functionSignature, 1,
Collections.singletonList(new LiteralExpr(new StringLiteral(singleArg))),
callExpr.getAggregateFilterExpr(), step);
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 a0ffdf2..b47eb6e 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
@@ -44,7 +44,7 @@
@Override
public Void visit(LoadStatement loadStmt, MetadataProvider metadataProvider) throws CompilationException {
Triple<DataverseName, String, Boolean> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
- loadStmt.getDataverseName(), loadStmt.getDatasetName(), loadStmt.getSourceLocation());
+ loadStmt.getDataverseName(), loadStmt.getDatasetName(), false, loadStmt.getSourceLocation());
if (dsName != null) {
loadStmt.setDataverseName(dsName.first);
loadStmt.setDatasetName(dsName.second);
@@ -55,7 +55,7 @@
@Override
public Void visit(InsertStatement insertStmt, MetadataProvider metadataProvider) throws CompilationException {
Triple<DataverseName, String, Boolean> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
- insertStmt.getDataverseName(), insertStmt.getDatasetName(), insertStmt.getSourceLocation());
+ insertStmt.getDataverseName(), insertStmt.getDatasetName(), false, insertStmt.getSourceLocation());
if (dsName != null) {
insertStmt.setDataverseName(dsName.first);
insertStmt.setDatasetName(dsName.second);
@@ -66,7 +66,7 @@
@Override
public Void visit(DeleteStatement deleteStmt, MetadataProvider metadataProvider) throws CompilationException {
Triple<DataverseName, String, Boolean> dsName = resolveDatasetNameUsingSynonyms(metadataProvider,
- deleteStmt.getDataverseName(), deleteStmt.getDatasetName(), deleteStmt.getSourceLocation());
+ deleteStmt.getDataverseName(), deleteStmt.getDatasetName(), false, deleteStmt.getSourceLocation());
if (dsName != null) {
deleteStmt.setDataverseName(dsName.first);
deleteStmt.setDatasetName(dsName.second);
@@ -75,9 +75,10 @@
}
private Triple<DataverseName, String, Boolean> resolveDatasetNameUsingSynonyms(MetadataProvider metadataProvider,
- DataverseName dataverseName, String datasetName, SourceLocation sourceLoc) throws CompilationException {
+ DataverseName dataverseName, String datasetName, boolean includingViews, SourceLocation sourceLoc)
+ throws CompilationException {
try {
- return metadataProvider.resolveDatasetNameUsingSynonyms(dataverseName, datasetName);
+ return metadataProvider.resolveDatasetNameUsingSynonyms(dataverseName, datasetName, includingViews);
} catch (AlgebricksException e) {
throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, sourceLoc, e.getMessage());
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index c4c86f4..cae5400 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -74,6 +74,7 @@
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.common.metadata.DatasetFullyQualifiedName;
import org.apache.asterix.lang.common.base.AbstractClause;
import org.apache.asterix.lang.common.base.AbstractLangExpression;
import org.apache.asterix.lang.common.base.AbstractStatement;
@@ -135,6 +136,7 @@
import org.apache.asterix.lang.common.statement.CreateSynonymStatement;
import org.apache.asterix.lang.common.statement.CreateFullTextFilterStatement;
import org.apache.asterix.lang.common.statement.CreateFullTextConfigStatement;
+import org.apache.asterix.lang.common.statement.CreateViewStatement;
import org.apache.asterix.lang.common.statement.DatasetDecl;
import org.apache.asterix.lang.common.statement.DataverseDecl;
import org.apache.asterix.lang.common.statement.DataverseDropStatement;
@@ -162,6 +164,8 @@
import org.apache.asterix.lang.common.statement.TypeDropStatement;
import org.apache.asterix.lang.common.statement.UpdateStatement;
import org.apache.asterix.lang.common.statement.UpsertStatement;
+import org.apache.asterix.lang.common.statement.ViewDecl;
+import org.apache.asterix.lang.common.statement.ViewDropStatement;
import org.apache.asterix.lang.common.statement.WriteStatement;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.struct.OperatorType;
@@ -414,6 +418,22 @@
});
}
+ @Override
+ public ViewDecl parseViewBody(DatasetFullyQualifiedName viewName) throws CompilationException {
+ return parseImpl(new ParseFunction<ViewDecl>() {
+ @Override
+ public ViewDecl parse() throws ParseException {
+ DataverseName dataverse = defaultDataverse;
+ defaultDataverse = viewName.getDataverseName();
+ createNewScope();
+ Expression viewBodyExpr = SQLPPParser.this.ViewBody();
+ removeCurrentScope();
+ defaultDataverse = dataverse;
+ return new ViewDecl(viewName, viewBodyExpr);
+ }
+ });
+ }
+
private <T> T parseImpl(ParseFunction<T> parseFunction) throws CompilationException {
warningCollector.clear();
hintCollector.clear();
@@ -796,6 +816,7 @@
| stmt = CreateFeedStatement(startToken)
| stmt = CreateFeedPolicyStatement(startToken)
| stmt = CreateFullTextStatement(startToken)
+ | stmt = CreateViewStatement(startToken, false)
)
{
return stmt;
@@ -811,6 +832,7 @@
<OR> <IDENTIFIER> { replaceToken = token; }
(
stmt = CreateFunctionStatement(startStmtToken, true)
+ | stmt = CreateViewStatement(startStmtToken, true)
)
{
// check expected token here to make the grammar extension plugin happy
@@ -1381,6 +1403,65 @@
}
}
+CreateViewStatement CreateViewStatement(Token startStmtToken, boolean orReplace) throws ParseException:
+{
+ CreateViewStatement stmt = null;
+}
+{
+ <VIEW> stmt = ViewSpecification(startStmtToken, orReplace)
+ {
+ return stmt;
+ }
+}
+
+CreateViewStatement ViewSpecification(Token startStmtToken, boolean orReplace) throws ParseException:
+{
+ Pair<DataverseName, Identifier> nameComponents = null;
+ boolean ifNotExists = false;
+ Token beginPos = null, endPos = null;
+ Expression viewBodyExpr = null;
+ DataverseName currentDataverse = defaultDataverse;
+}
+{
+ nameComponents = QualifiedName()
+ ifNotExists = IfNotExists()
+ {
+ if (orReplace && ifNotExists) {
+ throw new SqlppParseException(getSourceLocation(token), "Unexpected IF NOT EXISTS");
+ }
+ }
+ <AS>
+ {
+ beginPos = token;
+ createNewScope();
+ if (nameComponents.first != null) {
+ defaultDataverse = nameComponents.first;
+ }
+ }
+ viewBodyExpr = ViewBody()
+ {
+ endPos = token;
+ String viewBody = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine,
+ endPos.endColumn + 1);
+ removeCurrentScope();
+ defaultDataverse = currentDataverse;
+ CreateViewStatement stmt = new CreateViewStatement(nameComponents.first, nameComponents.second.getValue(), viewBody,
+ viewBodyExpr, orReplace, ifNotExists);
+ return addSourceLocation(stmt, startStmtToken);
+ }
+}
+
+Expression ViewBody() throws ParseException:
+{
+ Expression viewBodyExpr = null;
+}
+{
+ viewBodyExpr = SelectExpression(true)
+ {
+ return viewBodyExpr;
+ }
+}
+
CreateFunctionStatement CreateFunctionStatement(Token startStmtToken, boolean orReplace) throws ParseException:
{
CreateFunctionStatement stmt = null;
@@ -1421,6 +1502,11 @@
signature = new FunctionSignature(fctName.dataverse, fctName.function, arity);
}
ifNotExists = IfNotExists()
+ {
+ if (orReplace && ifNotExists) {
+ throw new SqlppParseException(getSourceLocation(token), "Unexpected IF NOT EXISTS");
+ }
+ }
returnType = FunctionReturnType()
(
(
@@ -1457,9 +1543,6 @@
)
)
{
- if (orReplace && ifNotExists) {
- throw new SqlppParseException(getSourceLocation(startStmtToken), "Unexpected IF NOT EXISTS");
- }
defaultDataverse = currentDataverse;
return addSourceLocation(stmt, startStmtToken);
}
@@ -1852,6 +1935,7 @@
| stmt = DropFeedPolicyStatement(startToken)
| stmt = DropSynonymStatement(startToken)
| stmt = DropFullTextStatement(startToken)
+ | stmt = DropViewStatement(startToken)
)
{
return stmt;
@@ -1882,6 +1966,30 @@
}
}
+ViewDropStatement DropViewStatement(Token startStmtToken) throws ParseException:
+{
+ ViewDropStatement stmt = null;
+}
+{
+ <VIEW> stmt = DropViewSpecification(startStmtToken)
+ {
+ return stmt;
+ }
+}
+
+ViewDropStatement DropViewSpecification(Token startStmtToken) throws ParseException:
+{
+ Pair<DataverseName,Identifier> pairId = null;
+ boolean ifExists = false;
+}
+{
+ pairId = QualifiedName() ifExists = IfExists()
+ {
+ ViewDropStatement stmt = new ViewDropStatement(pairId.first, pairId.second, ifExists);
+ return addSourceLocation(stmt, startStmtToken);
+ }
+}
+
IndexDropStatement DropIndexStatement(Token startStmtToken) throws ParseException:
{
IndexDropStatement stmt = null;
@@ -4988,6 +5096,7 @@
| <USING : "using">
| <VALUE : "value">
| <VALUED : "valued">
+ | <VIEW : "view">
| <WHEN : "when">
| <WHERE : "where">
| <WITH : "with">
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 9975f4c..a5dda0d 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
@@ -20,7 +20,6 @@
package org.apache.asterix.metadata;
import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
-import static org.apache.asterix.common.exceptions.ErrorCode.FULL_TEXT_DEFAULT_CONFIG_CANNOT_BE_DELETED_OR_CREATED;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import java.rmi.RemoteException;
@@ -68,6 +67,7 @@
import org.apache.asterix.metadata.entities.DatasourceAdapter;
import org.apache.asterix.metadata.entities.Datatype;
import org.apache.asterix.metadata.entities.Dataverse;
+import org.apache.asterix.metadata.entities.DependencyKind;
import org.apache.asterix.metadata.entities.Feed;
import org.apache.asterix.metadata.entities.FeedConnection;
import org.apache.asterix.metadata.entities.FeedPolicyEntity;
@@ -80,6 +80,7 @@
import org.apache.asterix.metadata.entities.Node;
import org.apache.asterix.metadata.entities.NodeGroup;
import org.apache.asterix.metadata.entities.Synonym;
+import org.apache.asterix.metadata.entities.ViewDetails;
import org.apache.asterix.metadata.entitytupletranslators.CompactionPolicyTupleTranslator;
import org.apache.asterix.metadata.entitytupletranslators.DatasetTupleTranslator;
import org.apache.asterix.metadata.entitytupletranslators.DatasourceAdapterTupleTranslator;
@@ -772,15 +773,16 @@
@Override
public void dropDataset(TxnId txnId, DataverseName dataverseName, String datasetName, boolean force)
throws AlgebricksException {
- if (!force) {
- confirmDatasetCanBeDeleted(txnId, dataverseName, datasetName);
- }
-
Dataset dataset = getDataset(txnId, dataverseName, datasetName);
if (dataset == null) {
throw new AsterixException(org.apache.asterix.common.exceptions.ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE,
datasetName, dataverseName);
}
+ if (!force) {
+ String datasetTypeDisplayName = DatasetUtil.getDatasetTypeDisplayName(dataset.getDatasetType());
+ confirmDatasetCanBeDeleted(txnId, datasetTypeDisplayName, dataverseName, datasetName);
+ }
+
try {
// Delete entry from the 'datasets' dataset.
ITupleReference searchKey = createTuple(dataverseName, datasetName);
@@ -790,25 +792,37 @@
try {
datasetTuple = getTupleToBeDeleted(txnId, MetadataPrimaryIndexes.DATASET_DATASET, searchKey);
- // Delete entry(s) from the 'indexes' dataset.
- List<Index> datasetIndexes = getDatasetIndexes(txnId, dataverseName, datasetName);
- if (datasetIndexes != null) {
- for (Index index : datasetIndexes) {
- dropIndex(txnId, dataverseName, datasetName, index.getIndexName());
- }
- }
-
- if (dataset.getDatasetType() == DatasetType.EXTERNAL) {
- // Delete External Files
- // As a side effect, acquires an S lock on the 'ExternalFile' dataset
- // on behalf of txnId.
- List<ExternalFile> datasetFiles = getExternalFiles(txnId, dataset);
- if (datasetFiles != null && !datasetFiles.isEmpty()) {
- // Drop all external files in this dataset.
- for (ExternalFile file : datasetFiles) {
- dropExternalFile(txnId, dataverseName, file.getDatasetName(), file.getFileNumber());
+ switch (dataset.getDatasetType()) {
+ case INTERNAL:
+ // Delete entry(s) from the 'indexes' dataset.
+ List<Index> datasetIndexes = getDatasetIndexes(txnId, dataverseName, datasetName);
+ if (datasetIndexes != null) {
+ for (Index index : datasetIndexes) {
+ dropIndex(txnId, dataverseName, datasetName, index.getIndexName());
+ }
}
- }
+ break;
+ case EXTERNAL:
+ // Delete entry(s) from the 'indexes' dataset.
+ datasetIndexes = getDatasetIndexes(txnId, dataverseName, datasetName);
+ if (datasetIndexes != null) {
+ for (Index index : datasetIndexes) {
+ dropIndex(txnId, dataverseName, datasetName, index.getIndexName());
+ }
+ }
+ // Delete External Files
+ // As a side effect, acquires an S lock on the 'ExternalFile' dataset
+ // on behalf of txnId.
+ List<ExternalFile> datasetFiles = getExternalFiles(txnId, dataset);
+ if (datasetFiles != null && !datasetFiles.isEmpty()) {
+ // Drop all external files in this dataset.
+ for (ExternalFile file : datasetFiles) {
+ dropExternalFile(txnId, dataverseName, file.getDatasetName(), file.getFileNumber());
+ }
+ }
+ break;
+ case VIEW:
+ break;
}
} catch (HyracksDataException hde) {
// ignore this exception and continue deleting all relevant
@@ -1124,44 +1138,60 @@
// uses a type from this dataverse
// throw an error
List<Dataset> datasets = getAllDatasets(txnId);
- for (Dataset set : datasets) {
- if (set.getDataverseName().equals(dataverseName)) {
+ for (Dataset dataset : datasets) {
+ if (dataset.getDataverseName().equals(dataverseName)) {
continue;
}
- if (set.getItemTypeDataverseName().equals(dataverseName)) {
+ if (dataset.getItemTypeDataverseName().equals(dataverseName)) {
throw new AsterixException(
org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS, "type",
- TypeUtil.getFullyQualifiedDisplayName(set.getItemTypeDataverseName(), set.getItemTypeName()),
- dataset(), DatasetUtil.getFullyQualifiedDisplayName(set));
+ TypeUtil.getFullyQualifiedDisplayName(dataset.getItemTypeDataverseName(),
+ dataset.getItemTypeName()),
+ dataset(), DatasetUtil.getFullyQualifiedDisplayName(dataset));
}
- if (set.getMetaItemTypeDataverseName() != null
- && set.getMetaItemTypeDataverseName().equals(dataverseName)) {
+ if (dataset.hasMetaPart() && dataset.getMetaItemTypeDataverseName().equals(dataverseName)) {
throw new AsterixException(
org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS, "type",
- TypeUtil.getFullyQualifiedDisplayName(set.getMetaItemTypeDataverseName(),
- set.getMetaItemTypeName()),
- dataset(), DatasetUtil.getFullyQualifiedDisplayName(set));
+ TypeUtil.getFullyQualifiedDisplayName(dataset.getMetaItemTypeDataverseName(),
+ dataset.getMetaItemTypeName()),
+ dataset(), DatasetUtil.getFullyQualifiedDisplayName(dataset));
+ }
+ if (dataset.getDatasetType() == DatasetType.VIEW) {
+ ViewDetails viewDetails = (ViewDetails) dataset.getDatasetDetails();
+ List<DependencyKind> dependenciesSchema = ViewDetails.DEPENDENCIES_SCHEMA;
+ List<List<Triple<DataverseName, String, String>>> dependencies = viewDetails.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)) {
+ DependencyKind dependencyKind = dependenciesSchema.get(i);
+ throw new AsterixException(
+ org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS,
+ dependencyKind, dependencyKind.getDependencyDisplayName(dependency), "view",
+ DatasetUtil.getFullyQualifiedDisplayName(dataset));
+ }
+ }
+ }
}
}
// If a function from a DIFFERENT 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;
}
+ List<DependencyKind> dependenciesSchema = Function.DEPENDENCIES_SCHEMA;
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];
+ DependencyKind dependencyKind = dependenciesSchema.get(i);
throw new AsterixException(
org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_DATAVERSE_DEPENDENT_EXISTS,
- functionDependencyKind, functionDependencyKind.getDependencyDisplayName(dependency),
- "function", function.getSignature());
+ dependencyKind, dependencyKind.getDependencyDisplayName(dependency), "function",
+ function.getSignature());
}
}
}
@@ -1186,6 +1216,7 @@
}
private void confirmFunctionCanBeDeleted(TxnId txnId, FunctionSignature signature) throws AlgebricksException {
+ confirmFunctionIsUnusedByViews(txnId, signature);
confirmFunctionIsUnusedByFunctions(txnId, signature);
// if any other feed connection uses this function, throw an error
@@ -1200,18 +1231,34 @@
}
}
- private void confirmFunctionIsUnusedByFunctions(TxnId txnId, FunctionSignature signature)
- throws AlgebricksException {
- confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.FUNCTION, signature.getDataverseName(),
+ private void confirmFunctionIsUnusedByViews(TxnId txnId, FunctionSignature signature) throws AlgebricksException {
+ confirmObjectIsUnusedByViews(txnId, "function", DependencyKind.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 {
+ private void confirmFunctionIsUnusedByFunctions(TxnId txnId, FunctionSignature signature)
+ throws AlgebricksException {
+ confirmObjectIsUnusedByFunctions(txnId, "function", DependencyKind.FUNCTION, signature.getDataverseName(),
+ signature.getName(), Integer.toString(signature.getArity()));
+ }
+
+ private void confirmObjectIsUnusedByFunctions(TxnId txnId, String objectKindDisplayName,
+ DependencyKind 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) {
+ confirmObjectIsUnusedByFunctionsImpl(functions, objectKindDisplayName, dependencyKind, dataverseName,
+ objectName, objectArg);
+ }
+
+ private void confirmObjectIsUnusedByFunctionsImpl(List<Function> allFunctions, String objectKindDisplayName,
+ DependencyKind dependencyKind, DataverseName dataverseName, String objectName, String objectArg)
+ throws AlgebricksException {
+ int functionDependencyIdx = Function.DEPENDENCIES_SCHEMA.indexOf(dependencyKind);
+ if (functionDependencyIdx < 0) {
+ throw new AlgebricksException(ErrorCode.ILLEGAL_STATE);
+ }
+ for (Function function : allFunctions) {
List<List<Triple<DataverseName, String, String>>> functionDependencies = function.getDependencies();
if (functionDependencyIdx < functionDependencies.size()) {
List<Triple<DataverseName, String, String>> functionObjectDependencies =
@@ -1222,9 +1269,46 @@
&& (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());
+ objectKindDisplayName, dependencyKind.getDependencyDisplayName(dependency),
+ "function", function.getSignature());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void confirmObjectIsUnusedByViews(TxnId txnId, String objectKindDisplayName, DependencyKind dependencyKind,
+ DataverseName dataverseName, String objectName, String objectArg) throws AlgebricksException {
+ // If any function uses this object, throw an error
+ List<Dataset> datasets = getAllDatasets(txnId);
+ confirmObjectIsUnusedByViewsImpl(datasets, objectKindDisplayName, dependencyKind, dataverseName, objectName,
+ objectArg);
+ }
+
+ private void confirmObjectIsUnusedByViewsImpl(List<Dataset> allDatasets, String objectKindDisplayName,
+ DependencyKind dependencyKind, DataverseName dataverseName, String objectName, String objectArg)
+ throws AlgebricksException {
+ int viewDependencyIdx = ViewDetails.DEPENDENCIES_SCHEMA.indexOf(dependencyKind);
+ if (viewDependencyIdx < 0) {
+ throw new AlgebricksException(ErrorCode.ILLEGAL_STATE);
+ }
+ for (Dataset dataset : allDatasets) {
+ if (dataset.getDatasetType() == DatasetType.VIEW) {
+ ViewDetails viewDetails = (ViewDetails) dataset.getDatasetDetails();
+ List<List<Triple<DataverseName, String, String>>> viewDependencies = viewDetails.getDependencies();
+ if (viewDependencyIdx < viewDependencies.size()) {
+ List<Triple<DataverseName, String, String>> viewObjectDependencies =
+ viewDependencies.get(viewDependencyIdx);
+ if (viewObjectDependencies != null) {
+ for (Triple<DataverseName, String, String> dependency : viewObjectDependencies) {
+ 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,
+ objectKindDisplayName, dependencyKind.getDependencyDisplayName(dependency),
+ "view", DatasetUtil.getFullyQualifiedDisplayName(dataset));
+ }
}
}
}
@@ -1235,7 +1319,8 @@
private void confirmFullTextConfigCanBeDeleted(TxnId txnId, DataverseName dataverseNameFullTextConfig,
String configName) throws AlgebricksException {
if (Strings.isNullOrEmpty(configName)) {
- throw new MetadataException(FULL_TEXT_DEFAULT_CONFIG_CANNOT_BE_DELETED_OR_CREATED);
+ throw new MetadataException(
+ org.apache.asterix.common.exceptions.ErrorCode.FULL_TEXT_DEFAULT_CONFIG_CANNOT_BE_DELETED_OR_CREATED);
}
// If any index uses this full-text config, throw an error
@@ -1263,14 +1348,21 @@
}
}
- private void confirmDatasetCanBeDeleted(TxnId txnId, DataverseName dataverseName, String datasetName)
- throws AlgebricksException {
- confirmDatasetIsUnusedByFunctions(txnId, dataverseName, datasetName);
+ private void confirmDatasetCanBeDeleted(TxnId txnId, String datasetTypeDisplayName, DataverseName dataverseName,
+ String datasetName) throws AlgebricksException {
+ confirmDatasetIsUnusedByFunctions(txnId, datasetTypeDisplayName, dataverseName, datasetName);
+ confirmDatasetIsUnusedByViews(txnId, datasetTypeDisplayName, dataverseName, datasetName);
}
- private void confirmDatasetIsUnusedByFunctions(TxnId txnId, DataverseName dataverseName, String datasetName)
- throws AlgebricksException {
- confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.DATASET, dataverseName, datasetName,
+ private void confirmDatasetIsUnusedByFunctions(TxnId txnId, String datasetKindDisplayName,
+ DataverseName dataverseName, String datasetName) throws AlgebricksException {
+ confirmObjectIsUnusedByFunctions(txnId, datasetKindDisplayName, DependencyKind.DATASET, dataverseName,
+ datasetName, null);
+ }
+
+ private void confirmDatasetIsUnusedByViews(TxnId txnId, String datasetKindDisplayName, DataverseName dataverseName,
+ String datasetName) throws AlgebricksException {
+ confirmObjectIsUnusedByViews(txnId, datasetKindDisplayName, DependencyKind.DATASET, dataverseName, datasetName,
null);
}
@@ -1320,14 +1412,21 @@
throws AlgebricksException {
// If any dataset uses this type, throw an error
List<Dataset> datasets = getAllDatasets(txnId);
- for (Dataset set : datasets) {
- if (set.getItemTypeName().equals(datatypeName) && set.getItemTypeDataverseName().equals(dataverseName)) {
+ for (Dataset dataset : datasets) {
+ if ((dataset.getItemTypeName().equals(datatypeName)
+ && dataset.getItemTypeDataverseName().equals(dataverseName))
+ || ((dataset.hasMetaPart() && dataset.getMetaItemTypeName().equals(datatypeName)
+ && dataset.getMetaItemTypeDataverseName().equals(dataverseName)))) {
throw new AsterixException(
org.apache.asterix.common.exceptions.ErrorCode.CANNOT_DROP_OBJECT_DEPENDENT_EXISTS, "type",
TypeUtil.getFullyQualifiedDisplayName(dataverseName, datatypeName), dataset(),
- DatasetUtil.getFullyQualifiedDisplayName(set));
+ DatasetUtil.getFullyQualifiedDisplayName(dataset));
}
}
+
+ // additionally, if a view uses this type, throw an error
+ // Note: for future use. currently views don't have any type dependencies
+ confirmObjectIsUnusedByViewsImpl(datasets, null, DependencyKind.TYPE, dataverseName, datatypeName, null);
}
private void confirmDatatypeIsUnusedByDatatypes(TxnId txnId, DataverseName dataverseName, String datatypeName)
@@ -1357,8 +1456,7 @@
private void confirmDatatypeIsUnusedByFunctions(TxnId txnId, DataverseName dataverseName, String dataTypeName)
throws AlgebricksException {
- confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.TYPE, dataverseName, dataTypeName,
- null);
+ confirmObjectIsUnusedByFunctions(txnId, "datatype", DependencyKind.TYPE, dataverseName, dataTypeName, null);
}
private void confirmFullTextFilterCanBeDeleted(TxnId txnId, DataverseName dataverseName, String fullTextFilterName)
@@ -2300,12 +2398,17 @@
private void confirmSynonymCanBeDeleted(TxnId txnId, DataverseName dataverseName, String synonymName)
throws AlgebricksException {
confirmSynonymIsUnusedByFunctions(txnId, dataverseName, synonymName);
+ confirmSynonymIsUnusedByViews(txnId, dataverseName, synonymName);
}
private void confirmSynonymIsUnusedByFunctions(TxnId txnId, DataverseName dataverseName, String synonymName)
throws AlgebricksException {
- confirmObjectIsUnusedByFunctions(txnId, Function.FunctionDependencyKind.SYNONYM, dataverseName, synonymName,
- null);
+ confirmObjectIsUnusedByFunctions(txnId, "synonym", DependencyKind.SYNONYM, dataverseName, synonymName, null);
+ }
+
+ private void confirmSynonymIsUnusedByViews(TxnId txnId, DataverseName dataverseName, String synonymName)
+ throws AlgebricksException {
+ confirmObjectIsUnusedByViews(txnId, "synonym", DependencyKind.SYNONYM, dataverseName, synonymName, null);
}
@Override
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataBootstrap.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataBootstrap.java
index 125db21..fd0d30b 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataBootstrap.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataBootstrap.java
@@ -507,6 +507,10 @@
private static void recoverDataset(MetadataTransactionContext mdTxnCtx, Dataset dataset)
throws AlgebricksException {
+ if (dataset.getDatasetType() == DatasetType.VIEW) {
+ // Views don't need any recovery and cannot be in a pending state
+ return;
+ }
if (dataset.getPendingOp() != MetadataUtil.PENDING_NO_OP) {
// drop pending dataset
MetadataManager.INSTANCE.dropDataset(mdTxnCtx, dataset.getDataverseName(), dataset.getDatasetName(), true);
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java
index 2e75319..ef9f5d7 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/MetadataRecordTypes.java
@@ -107,6 +107,7 @@
public static final String FIELD_NAME_TYPE = "Type";
public static final String FIELD_NAME_UNORDERED_LIST = "UnorderedList";
public static final String FIELD_NAME_VALUE = "Value";
+ public static final String FIELD_NAME_VIEW_DETAILS = "ViewDetails";
public static final String FIELD_NAME_WORKING_MEMORY_SIZE = "WorkingMemorySize";
public static final String FIELD_NAME_APPLIED_FUNCTIONS = "AppliedFunctions";
public static final String FIELD_NAME_WHERE_CLAUSE = "WhereClause";
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataManagerUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataManagerUtil.java
index 1376008..ee629b1 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataManagerUtil.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataManagerUtil.java
@@ -18,14 +18,13 @@
*/
package org.apache.asterix.metadata.declared;
-import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
import static org.apache.asterix.common.utils.IdentifierUtil.dataverse;
import java.util.ArrayList;
import java.util.List;
import org.apache.asterix.common.cluster.IClusterStateManager;
-import org.apache.asterix.common.config.DatasetConfig.DatasetType;
+import org.apache.asterix.common.config.DatasetConfig;
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.metadata.DataverseName;
@@ -103,17 +102,25 @@
return adapter;
}
- public static Dataset findDataset(MetadataTransactionContext mdTxnCtx, DataverseName dataverseName, String dataset)
- throws AlgebricksException {
- return MetadataManager.INSTANCE.getDataset(mdTxnCtx, dataverseName, dataset);
+ public static Dataset findDataset(MetadataTransactionContext mdTxnCtx, DataverseName dataverseName,
+ String datasetName, boolean includingViews) throws AlgebricksException {
+ Dataset dataset = MetadataManager.INSTANCE.getDataset(mdTxnCtx, dataverseName, datasetName);
+ if (!includingViews && dataset != null && dataset.getDatasetType() == DatasetConfig.DatasetType.VIEW) {
+ return null;
+ }
+ return dataset;
+ }
+
+ public static Dataset findDataset(MetadataTransactionContext mdTxnCtx, DataverseName dataverseName,
+ String datasetName) throws AlgebricksException {
+ return findDataset(mdTxnCtx, dataverseName, datasetName, false);
}
public static Dataset findExistingDataset(MetadataTransactionContext mdTxnCtx, DataverseName dataverseName,
String datasetName) throws AlgebricksException {
Dataset dataset = findDataset(mdTxnCtx, dataverseName, datasetName);
if (dataset == null) {
- throw new AlgebricksException(
- "Unknown " + dataset() + " " + datasetName + " in " + dataverse() + " " + dataverseName);
+ throw new AsterixException(ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE, datasetName, dataverseName);
}
return dataset;
}
@@ -185,13 +192,25 @@
MetadataTransactionContext mdTxnCtx, DataSourceId id) throws AlgebricksException {
Dataset dataset = findDataset(mdTxnCtx, id.getDataverseName(), id.getDatasourceName());
if (dataset == null) {
- throw new AlgebricksException("Datasource with id " + id + " was not found.");
+ throw new AsterixException(ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE, id.getDatasourceName(),
+ id.getDataverseName());
}
+ byte datasourceType;
+ switch (dataset.getDatasetType()) {
+ case INTERNAL:
+ datasourceType = DataSource.Type.INTERNAL_DATASET;
+ break;
+ case EXTERNAL:
+ datasourceType = DataSource.Type.EXTERNAL_DATASET;
+ break;
+ default:
+ throw new AsterixException(ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE, id.getDatasourceName(),
+ id.getDataverseName());
+ }
+
IAType itemType = findType(mdTxnCtx, dataset.getItemTypeDataverseName(), dataset.getItemTypeName());
IAType metaItemType = findType(mdTxnCtx, dataset.getMetaItemTypeDataverseName(), dataset.getMetaItemTypeName());
INodeDomain domain = findNodeDomain(clusterStateManager, mdTxnCtx, dataset.getNodeGroupName());
- byte datasourceType = dataset.getDatasetType().equals(DatasetType.EXTERNAL) ? DataSource.Type.EXTERNAL_DATASET
- : DataSource.Type.INTERNAL_DATASET;
return new DatasetDataSource(id, dataset, itemType, metaItemType, datasourceType, dataset.getDatasetDetails(),
domain);
}
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 d970b3a..6f91572 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
@@ -20,7 +20,6 @@
import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.PLURAL;
import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
-import static org.apache.asterix.common.utils.IdentifierUtil.dataverse;
import static org.apache.asterix.metadata.utils.MetadataConstants.METADATA_OBJECT_NAME_INVALID_CHARS;
import java.io.File;
@@ -360,13 +359,18 @@
}
public Dataset findDataset(DataverseName dataverseName, String datasetName) throws AlgebricksException {
+ return findDataset(dataverseName, datasetName, false);
+ }
+
+ public Dataset findDataset(DataverseName dataverseName, String datasetName, boolean includingViews)
+ throws AlgebricksException {
DataverseName dvName = getActiveDataverseName(dataverseName);
if (dvName == null) {
return null;
}
appCtx.getMetadataLockManager().acquireDataverseReadLock(locks, dvName);
appCtx.getMetadataLockManager().acquireDatasetReadLock(locks, dvName, datasetName);
- return MetadataManagerUtil.findDataset(mdTxnCtx, dvName, datasetName);
+ return MetadataManagerUtil.findDataset(mdTxnCtx, dvName, datasetName, includingViews);
}
public INodeDomain findNodeDomain(String nodeGroupName) throws AlgebricksException {
@@ -436,13 +440,13 @@
}
public Triple<DataverseName, String, Boolean> resolveDatasetNameUsingSynonyms(DataverseName dataverseName,
- String datasetName) throws AlgebricksException {
+ String datasetName, boolean includingViews) throws AlgebricksException {
DataverseName dvName = getActiveDataverseName(dataverseName);
if (dvName == null) {
return null;
}
Synonym synonym = null;
- while (MetadataManagerUtil.findDataset(mdTxnCtx, dvName, datasetName) == null) {
+ while (MetadataManagerUtil.findDataset(mdTxnCtx, dvName, datasetName, includingViews) == null) {
synonym = findSynonym(dvName, datasetName);
if (synonym == null) {
return null;
@@ -986,11 +990,11 @@
List<LogicalVariable> primaryKeys, LogicalVariable payload, List<LogicalVariable> filterKeys,
List<LogicalVariable> additionalNonFilterFields, RecordDescriptor recordDesc, JobGenContext context,
JobSpecification spec) throws AlgebricksException {
+ DataverseName dataverseName = dataSource.getId().getDataverseName();
String datasetName = dataSource.getId().getDatasourceName();
- Dataset dataset = findDataset(dataSource.getId().getDataverseName(), datasetName);
+ Dataset dataset = findDataset(dataverseName, datasetName);
if (dataset == null) {
- throw new AlgebricksException("Unknown " + dataset() + " " + datasetName + " in " + dataverse() + " "
- + dataSource.getId().getDataverseName());
+ throw new AsterixException(ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE, datasetName, dataverseName);
}
int numKeys = primaryKeys.size();
int numFilterFields = DatasetUtil.getFilterField(dataset) == null ? 0 : 1;
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 34e0c41..37e22ed 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
@@ -389,7 +389,7 @@
mdTxnCtx.setValue(MetadataManager.INSTANCE.beginTransaction());
bActiveTxn.setValue(true);
metadataProvider.setMetadataTxnContext(mdTxnCtx.getValue());
- } else {
+ } else if (getDatasetType() == DatasetType.EXTERNAL) {
// External dataset
ExternalDatasetsRegistry.INSTANCE.removeDatasetInfo(this);
// #. prepare jobs to drop the datatset and the indexes in NC
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/DependencyKind.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/DependencyKind.java
new file mode 100644
index 0000000..19939f9
--- /dev/null
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/DependencyKind.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.metadata.entities;
+
+import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
+
+import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.metadata.utils.DatasetUtil;
+import org.apache.asterix.metadata.utils.MetadataUtil;
+import org.apache.asterix.metadata.utils.TypeUtil;
+import org.apache.hyracks.algebricks.common.utils.Triple;
+
+public enum DependencyKind {
+ 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;
+
+ DependencyKind(
+ 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);
+ }
+
+ @Override
+ public String toString() {
+ return this == DATASET ? dataset() + " (or view)" : name().toLowerCase();
+ }
+}
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 a9fa024..8853c02 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,8 +18,6 @@
*/
package org.apache.asterix.metadata.entities;
-import static org.apache.asterix.common.utils.IdentifierUtil.dataset;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -30,9 +28,6 @@
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;
@@ -166,12 +161,15 @@
return cache.dropFunction(this);
}
+ public static List<DependencyKind> DEPENDENCIES_SCHEMA =
+ Arrays.asList(DependencyKind.DATASET, DependencyKind.FUNCTION, DependencyKind.TYPE, DependencyKind.SYNONYM);
+
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);
+ List<List<Triple<DataverseName, String, String>>> depList = new ArrayList<>(DEPENDENCIES_SCHEMA.size());
depList.add(datasetDependencies);
depList.add(functionDependencies);
depList.add(typeDependencies);
@@ -180,29 +178,4 @@
}
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);
- }
-
- @Override
- public String toString() {
- return this == DATASET ? dataset() : name().toLowerCase();
- }
- }
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/ViewDetails.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/ViewDetails.java
new file mode 100644
index 0000000..5c884d9
--- /dev/null
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/ViewDetails.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.metadata.entities;
+
+import static org.apache.asterix.om.types.AOrderedListType.FULL_OPEN_ORDEREDLIST_TYPE;
+
+import java.io.DataOutput;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.asterix.builders.IARecordBuilder;
+import org.apache.asterix.builders.OrderedListBuilder;
+import org.apache.asterix.builders.RecordBuilder;
+import org.apache.asterix.common.config.DatasetConfig;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.metadata.IDatasetDetails;
+import org.apache.asterix.metadata.bootstrap.MetadataRecordTypes;
+import org.apache.asterix.metadata.entitytupletranslators.AbstractTupleTranslator;
+import org.apache.asterix.om.base.AMutableString;
+import org.apache.asterix.om.base.AString;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.utils.RecordUtil;
+import org.apache.hyracks.algebricks.common.utils.Triple;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+
+public class ViewDetails implements IDatasetDetails {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String viewBody;
+
+ private final List<List<Triple<DataverseName, String, String>>> dependencies;
+
+ public ViewDetails(String viewBody, List<List<Triple<DataverseName, String, String>>> dependencies) {
+ this.viewBody = Objects.requireNonNull(viewBody);
+ this.dependencies = Objects.requireNonNull(dependencies);
+ }
+
+ public String getViewBody() {
+ return viewBody;
+ }
+
+ public List<List<Triple<DataverseName, String, String>>> getDependencies() {
+ return dependencies;
+ }
+
+ @Override
+ public DatasetConfig.DatasetType getDatasetType() {
+ return DatasetConfig.DatasetType.VIEW;
+ }
+
+ @Override
+ public void writeDatasetDetailsRecordType(DataOutput out) throws HyracksDataException {
+ IARecordBuilder viewRecordBuilder = new RecordBuilder();
+ viewRecordBuilder.reset(RecordUtil.FULLY_OPEN_RECORD_TYPE);
+
+ ArrayBackedValueStorage fieldName = new ArrayBackedValueStorage();
+ ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
+ ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
+
+ AMutableString aString = new AMutableString("");
+ ISerializerDeserializer<AString> stringSerde =
+ SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING);
+
+ // write field 'Definition'
+ fieldName.reset();
+ aString.setValue(MetadataRecordTypes.FIELD_NAME_DEFINITION);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+ fieldValue.reset();
+ aString.setValue(viewBody);
+ stringSerde.serialize(aString, fieldValue.getDataOutput());
+ viewRecordBuilder.addField(fieldName, fieldValue);
+
+ // write field 'Dependencies'
+ if (!dependencies.isEmpty()) {
+ fieldName.reset();
+ aString.setValue(MetadataRecordTypes.FIELD_NAME_DEPENDENCIES);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+
+ OrderedListBuilder dependenciesListBuilder = new OrderedListBuilder();
+ OrderedListBuilder dependencyListBuilder = new OrderedListBuilder();
+ OrderedListBuilder dependencyNameListBuilder = new OrderedListBuilder();
+ List<String> dependencySubnames = new ArrayList<>(3);
+
+ dependenciesListBuilder.reset(FULL_OPEN_ORDEREDLIST_TYPE);
+ for (List<Triple<DataverseName, String, String>> dependenciesList : dependencies) {
+ dependencyListBuilder.reset(FULL_OPEN_ORDEREDLIST_TYPE);
+ for (Triple<DataverseName, String, String> dependency : dependenciesList) {
+ dependencyNameListBuilder.reset(FULL_OPEN_ORDEREDLIST_TYPE);
+ dependencySubnames.clear();
+ AbstractTupleTranslator.getDependencySubNames(dependency, dependencySubnames);
+ for (String subName : dependencySubnames) {
+ itemValue.reset();
+ aString.setValue(subName);
+ stringSerde.serialize(aString, itemValue.getDataOutput());
+ dependencyNameListBuilder.addItem(itemValue);
+ }
+ itemValue.reset();
+ dependencyNameListBuilder.write(itemValue.getDataOutput(), true);
+ dependencyListBuilder.addItem(itemValue);
+ }
+ itemValue.reset();
+ dependencyListBuilder.write(itemValue.getDataOutput(), true);
+ dependenciesListBuilder.addItem(itemValue);
+ }
+ fieldValue.reset();
+ dependenciesListBuilder.write(fieldValue.getDataOutput(), true);
+ viewRecordBuilder.addField(fieldName, fieldValue);
+ }
+
+ viewRecordBuilder.write(out, true);
+ }
+
+ public static List<DependencyKind> DEPENDENCIES_SCHEMA =
+ Arrays.asList(DependencyKind.DATASET, DependencyKind.FUNCTION, DependencyKind.TYPE, DependencyKind.SYNONYM);
+
+ 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<>(DEPENDENCIES_SCHEMA.size());
+ depList.add(datasetDependencies);
+ depList.add(functionDependencies);
+ depList.add(typeDependencies);
+ if (!synonymDependencies.isEmpty()) {
+ depList.add(synonymDependencies);
+ }
+ return depList;
+ }
+}
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 a35246f..c4f1377 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
@@ -22,9 +22,11 @@
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
+import java.util.Collection;
import org.apache.asterix.builders.IARecordBuilder;
import org.apache.asterix.builders.RecordBuilder;
+import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
import org.apache.asterix.metadata.api.IMetadataEntityTupleTranslator;
import org.apache.asterix.metadata.api.IMetadataIndex;
@@ -33,11 +35,13 @@
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.AOrderedList;
import org.apache.asterix.om.base.ARecord;
import org.apache.asterix.om.base.AString;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.BuiltinType;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
@@ -113,4 +117,30 @@
protected abstract T createMetadataEntityFromARecord(ARecord aRecord)
throws HyracksDataException, AlgebricksException;
+
+ public static void getDependencySubNames(Triple<DataverseName, String, String> dependency,
+ Collection<? super String> outSubnames) {
+ outSubnames.add(dependency.first.getCanonicalForm());
+ if (dependency.second != null) {
+ outSubnames.add(dependency.second);
+ }
+ if (dependency.third != null) {
+ outSubnames.add(dependency.third);
+ }
+ }
+
+ public static Triple<DataverseName, String, String> getDependency(AOrderedList dependencySubnames)
+ throws AlgebricksException {
+ String dataverseCanonicalName = ((AString) dependencySubnames.getItem(0)).getStringValue();
+ DataverseName dataverseName = DataverseName.createFromCanonicalForm(dataverseCanonicalName);
+ String second = null, third = null;
+ int ln = dependencySubnames.size();
+ if (ln > 1) {
+ second = ((AString) dependencySubnames.getItem(1)).getStringValue();
+ if (ln > 2) {
+ third = ((AString) dependencySubnames.getItem(2)).getStringValue();
+ }
+ }
+ return new Triple<>(dataverseName, second, third);
+ }
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatasetTupleTranslator.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatasetTupleTranslator.java
index 19722ef..51753f2 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatasetTupleTranslator.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/DatasetTupleTranslator.java
@@ -44,6 +44,7 @@
import org.apache.asterix.metadata.entities.InternalDatasetDetails;
import org.apache.asterix.metadata.entities.InternalDatasetDetails.FileStructure;
import org.apache.asterix.metadata.entities.InternalDatasetDetails.PartitioningStrategy;
+import org.apache.asterix.metadata.entities.ViewDetails;
import org.apache.asterix.metadata.utils.DatasetUtil;
import org.apache.asterix.om.base.ABoolean;
import org.apache.asterix.om.base.ADateTime;
@@ -67,6 +68,7 @@
import org.apache.asterix.runtime.compression.CompressionManager;
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.HyracksDataException;
import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
@@ -200,7 +202,7 @@
break;
}
- case EXTERNAL:
+ case EXTERNAL: {
ARecord datasetDetailsRecord = (ARecord) datasetRecord
.getValueByPos(MetadataRecordTypes.DATASET_ARECORD_EXTERNALDETAILS_FIELD_INDEX);
String adapter = ((AString) datasetDetailsRecord
@@ -229,6 +231,41 @@
.getIntegerValue()];
datasetDetails = new ExternalDatasetDetails(adapter, properties, timestamp, state);
+ break;
+ }
+ case VIEW: {
+ int datasetDetailsFieldPos =
+ datasetRecord.getType().getFieldIndex(MetadataRecordTypes.FIELD_NAME_VIEW_DETAILS);
+ ARecord datasetDetailsRecord = (ARecord) datasetRecord.getValueByPos(datasetDetailsFieldPos);
+
+ // Definition
+ int definitionFieldPos =
+ datasetDetailsRecord.getType().getFieldIndex(MetadataRecordTypes.FIELD_NAME_DEFINITION);
+ String definition = ((AString) datasetDetailsRecord.getValueByPos(definitionFieldPos)).getStringValue();
+
+ // Dependencies
+ List<List<Triple<DataverseName, String, String>>> dependencies = Collections.emptyList();
+ int dependenciesFieldPos =
+ datasetDetailsRecord.getType().getFieldIndex(MetadataRecordTypes.FIELD_NAME_DEPENDENCIES);
+ if (dependenciesFieldPos >= 0) {
+ dependencies = new ArrayList<>();
+ IACursor dependenciesCursor =
+ ((AOrderedList) datasetDetailsRecord.getValueByPos(dependenciesFieldPos)).getCursor();
+ while (dependenciesCursor.next()) {
+ List<Triple<DataverseName, String, String>> dependencyList = new ArrayList<>();
+ IACursor qualifiedDependencyCursor = ((AOrderedList) dependenciesCursor.get()).getCursor();
+ while (qualifiedDependencyCursor.next()) {
+ Triple<DataverseName, String, String> dependency =
+ getDependency((AOrderedList) qualifiedDependencyCursor.get());
+ dependencyList.add(dependency);
+ }
+ dependencies.add(dependencyList);
+ }
+ }
+
+ datasetDetails = new ViewDetails(definition, dependencies);
+ break;
+ }
}
Map<String, String> hints = getDatasetHints(datasetRecord);
@@ -359,8 +396,19 @@
dataset.getCompactionPolicyProperties(), listBuilder, itemValue);
// write field 8/9
- fieldValue.reset();
- writeDatasetDetailsRecordType(recordBuilder, dataset, fieldValue.getDataOutput());
+ switch (dataset.getDatasetType()) {
+ case INTERNAL:
+ fieldValue.reset();
+ dataset.getDatasetDetails().writeDatasetDetailsRecordType(fieldValue.getDataOutput());
+ recordBuilder.addField(MetadataRecordTypes.DATASET_ARECORD_INTERNALDETAILS_FIELD_INDEX, fieldValue);
+ break;
+ case EXTERNAL:
+ fieldValue.reset();
+ dataset.getDatasetDetails().writeDatasetDetailsRecordType(fieldValue.getDataOutput());
+ recordBuilder.addField(MetadataRecordTypes.DATASET_ARECORD_EXTERNALDETAILS_FIELD_INDEX, fieldValue);
+ break;
+ // VIEW details are written later by {@code writeOpenFields()}
+ }
// write field 10
UnorderedListBuilder uListBuilder = new UnorderedListBuilder();
@@ -441,6 +489,19 @@
writeMetaPart(dataset);
writeRebalanceCount(dataset);
writeBlockLevelStorageCompression(dataset);
+ writeOpenDetails(dataset);
+ }
+
+ private void writeOpenDetails(Dataset dataset) throws HyracksDataException {
+ if (dataset.getDatasetType() == DatasetType.VIEW) {
+ // write ViewDetails field
+ fieldName.reset();
+ aString.setValue(MetadataRecordTypes.FIELD_NAME_VIEW_DETAILS);
+ stringSerde.serialize(aString, fieldName.getDataOutput());
+ fieldValue.reset();
+ dataset.getDatasetDetails().writeDatasetDetailsRecordType(fieldValue.getDataOutput());
+ recordBuilder.addField(fieldName, fieldValue);
+ }
}
private void writeMetaPart(Dataset dataset) throws HyracksDataException {
@@ -500,20 +561,6 @@
}
}
- protected void writeDatasetDetailsRecordType(IARecordBuilder recordBuilder, Dataset dataset, DataOutput dataOutput)
- throws HyracksDataException {
- dataset.getDatasetDetails().writeDatasetDetailsRecordType(dataOutput);
- switch (dataset.getDatasetType()) {
- case INTERNAL:
- recordBuilder.addField(MetadataRecordTypes.DATASET_ARECORD_INTERNALDETAILS_FIELD_INDEX, fieldValue);
- break;
- case EXTERNAL:
- recordBuilder.addField(MetadataRecordTypes.DATASET_ARECORD_EXTERNALDETAILS_FIELD_INDEX, fieldValue);
- break;
- }
-
- }
-
protected Map<String, String> getDatasetHints(ARecord datasetRecord) {
Map<String, String> hints = new HashMap<>();
String key;
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 ccae8a4..ef9c143 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
@@ -244,21 +244,6 @@
return new TypeSignature(typeDataverseName, typeName);
}
- private Triple<DataverseName, String, String> getDependency(AOrderedList dependencySubnames)
- throws AlgebricksException {
- String dataverseCanonicalName = ((AString) dependencySubnames.getItem(0)).getStringValue();
- DataverseName dataverseName = DataverseName.createFromCanonicalForm(dataverseCanonicalName);
- String second = null, third = null;
- int ln = dependencySubnames.size();
- if (ln > 1) {
- second = ((AString) dependencySubnames.getItem(1)).getStringValue();
- if (ln > 2) {
- third = ((AString) dependencySubnames.getItem(2)).getStringValue();
- }
- }
- return new Triple<>(dataverseName, second, third);
- }
-
private Map<String, String> getResources(ARecord functionRecord, String resourcesFieldName) {
Map<String, String> adaptorConfiguration = null;
final ARecordType functionType = functionRecord.getType();
@@ -381,11 +366,14 @@
dependenciesListBuilder.reset((AOrderedListType) MetadataRecordTypes.FUNCTION_RECORDTYPE
.getFieldTypes()[MetadataRecordTypes.FUNCTION_ARECORD_FUNCTION_DEPENDENCIES_FIELD_INDEX]);
List<List<Triple<DataverseName, String, String>>> dependenciesList = function.getDependencies();
+ List<String> subNames = new ArrayList<>();
for (List<Triple<DataverseName, String, String>> dependencies : dependenciesList) {
dependencyListBuilder.reset(listOfLists);
for (Triple<DataverseName, String, String> dependency : dependencies) {
dependencyNameListBuilder.reset(stringList);
- for (String subName : getDependencySubNames(dependency)) {
+ subNames.clear();
+ getDependencySubNames(dependency, subNames);
+ for (String subName : subNames) {
itemValue.reset();
aString.setValue(subName);
stringSerde.serialize(aString, itemValue.getDataOutput());
@@ -611,18 +599,6 @@
propertyRecordBuilder.write(out, true);
}
- private List<String> getDependencySubNames(Triple<DataverseName, String, String> dependency) {
- dependencySubnames.clear();
- dependencySubnames.add(dependency.first.getCanonicalForm());
- if (dependency.second != null) {
- dependencySubnames.add(dependency.second);
- }
- if (dependency.third != null) {
- dependencySubnames.add(dependency.third);
- }
- return dependencySubnames;
- }
-
// back-compat
private static List<String> decodeExternalIdentifierBackCompat(String encodedValue,
ExternalFunctionLanguage language) throws AlgebricksException {
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java
index 158efb2..143dc4c 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java
@@ -39,6 +39,7 @@
import org.apache.asterix.common.dataflow.ICcApplicationContext;
import org.apache.asterix.common.exceptions.ACIDException;
import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.common.transactions.IRecoveryManager;
import org.apache.asterix.external.indexing.IndexingConstants;
@@ -369,8 +370,7 @@
DataverseName dataverseName = dataverse.getDataverseName();
Dataset dataset = metadataProvider.findDataset(dataverseName, datasetName);
if (dataset == null) {
- throw new AsterixException(
- "Could not find " + dataset() + " " + datasetName + " in " + dataverse() + " " + dataverseName);
+ throw new AsterixException(ErrorCode.UNKNOWN_DATASET_IN_DATAVERSE, datasetName, dataverseName);
}
JobSpecification spec = RuntimeUtils.createJobSpecification(metadataProvider.getApplicationContext());
Pair<IFileSplitProvider, AlgebricksPartitionConstraint> splitsAndConstraint =
@@ -621,4 +621,11 @@
return nodeGroup;
}
+ public static String getDatasetTypeDisplayName(DatasetType datasetType) {
+ return datasetType == DatasetType.VIEW ? "view" : dataset();
+ }
+
+ public static boolean isNotView(Dataset dataset) {
+ return dataset.getDatasetType() != DatasetType.VIEW;
+ }
}