[NO ISSUE][COMP] Add support for compiler warnings
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Add support for compiler warnings during parsing,
AST rewriting and query optimization phases
- SQL++ parser emits warnings for unknown hints in
relational expression, between expression,
groupby clause and function call.
- Optimizer emits warning if hash group by hint cannot
be applied because there's no serializable aggregate
- Added testcases for these new warnings
Change-Id: Ic3c1e98c183cd214eea3e4fee24b2b7c46366b52
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3476
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
Reviewed-by: Murtadha Hubail <mhubail@apache.org>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
index 82ab296..ea3404d 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
@@ -33,6 +33,7 @@
import org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
import org.apache.hyracks.algebricks.core.rewriter.base.AlgebricksOptimizationContext;
import org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -45,10 +46,11 @@
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer nullableTypeComputer,
IConflictingTypeResolver conflictingTypeResovler, PhysicalOptimizationConfig physicalOptimizationConfig,
- AlgebricksPartitionConstraint clusterLocations, LogicalOperatorPrettyPrintVisitor prettyPrintVisitor) {
+ AlgebricksPartitionConstraint clusterLocations, LogicalOperatorPrettyPrintVisitor prettyPrintVisitor,
+ IWarningCollector warningCollector) {
super(varCounter, expressionEvalSizeComputer, mergeAggregationExpressionFactory, expressionTypeComputer,
nullableTypeComputer, conflictingTypeResovler, physicalOptimizationConfig, clusterLocations,
- prettyPrintVisitor);
+ prettyPrintVisitor, warningCollector);
}
public void addDataSource(DataSource dataSource) {
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 c5e9beb..64a4452 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
@@ -21,6 +21,7 @@
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -166,9 +167,7 @@
IResponsePrinter getResponsePrinter();
/**
- * Gets the warnings generated during compiling and exeucting a request
- *
- * @return the list of warnings
+ * Gets the warnings generated during compiling and executing a request
*/
- List<Warning> getWarnings();
+ void getWarnings(Collection<? super Warning> outWarnings);
}
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 3ab908b..69d998f 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
@@ -109,6 +109,7 @@
import org.apache.hyracks.api.config.IOptionType;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.exceptions.HyracksException;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.api.exceptions.SourceLocation;
import org.apache.hyracks.api.job.JobId;
import org.apache.hyracks.api.job.JobSpecification;
@@ -168,17 +169,18 @@
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer missableTypeComputer,
IConflictingTypeResolver conflictingTypeResolver, PhysicalOptimizationConfig physicalOptimizationConfig,
- AlgebricksPartitionConstraint clusterLocations) {
+ AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector) {
LogicalOperatorPrettyPrintVisitor prettyPrintVisitor = new LogicalOperatorPrettyPrintVisitor();
return new AsterixOptimizationContext(varCounter, expressionEvalSizeComputer,
mergeAggregationExpressionFactory, expressionTypeComputer, missableTypeComputer,
- conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, prettyPrintVisitor);
+ conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, prettyPrintVisitor,
+ warningCollector);
}
}
public Pair<IReturningStatement, Integer> reWriteQuery(List<FunctionDecl> declaredFunctions,
MetadataProvider metadataProvider, IReturningStatement q, SessionOutput output, boolean inlineUdfs,
- Collection<VarIdentifier> externalVars) throws CompilationException {
+ Collection<VarIdentifier> externalVars, IWarningCollector warningCollector) throws CompilationException {
if (q == null) {
return null;
}
@@ -187,15 +189,15 @@
generateExpressionTree(q);
}
IQueryRewriter rw = rewriterFactory.createQueryRewriter();
- rw.rewrite(declaredFunctions, q, metadataProvider, new LangRewritingContext(q.getVarCounter()), inlineUdfs,
- externalVars);
+ rw.rewrite(declaredFunctions, q, metadataProvider,
+ new LangRewritingContext(q.getVarCounter(), warningCollector), inlineUdfs, externalVars);
return new Pair<>(q, q.getVarCounter());
}
public JobSpecification compileQuery(IClusterInfoCollector clusterInfoCollector, MetadataProvider metadataProvider,
Query query, int varCounter, String outputDatasetName, SessionOutput output,
- ICompiledDmlStatement statement, Map<VarIdentifier, IAObject> externalVars, IResponsePrinter printer)
- throws AlgebricksException, ACIDException {
+ ICompiledDmlStatement statement, Map<VarIdentifier, IAObject> externalVars, IResponsePrinter printer,
+ IWarningCollector warningCollector) throws AlgebricksException, ACIDException {
// establish facts
final boolean isQuery = query != null;
@@ -240,6 +242,7 @@
builder.setExpressionTypeComputer(ExpressionTypeComputer.INSTANCE);
builder.setMissableTypeComputer(MissableTypeComputer.INSTANCE);
builder.setConflictingTypeResolver(ConflictingTypeResolver.INSTANCE);
+ builder.setWarningCollector(warningCollector);
int parallelism = getParallelism((String) querySpecificConfig.get(CompilerProperties.COMPILER_PARALLELISM_KEY),
compilerProperties.getParallelism());
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 0d5de57..db7075d 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -594,6 +594,7 @@
}
IParser parser = compilationProvider.getParserFactory().createParser(statementsText);
List<Statement> statements = parser.parse();
+ parser.getWarnings(warnings);
MetadataManager.INSTANCE.init();
IStatementExecutor translator = statementExecutorFactory.create((ICcApplicationContext) appCtx, statements,
sessionOutput, compilationProvider, componentProvider, responsePrinter);
@@ -605,7 +606,7 @@
optionalParameters, stmtParams, param.isMultiStatement());
translator.compileAndExecute(getHyracksClientConnection(), requestParameters);
execution.end();
- warnings.addAll(translator.getWarnings());
+ translator.getWarnings(warnings);
buildResponseResults(responsePrinter, sessionOutput, translator.getExecutionPlans(), warnings);
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
index 5663b12..e394c7a 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
@@ -21,8 +21,10 @@
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.asterix.algebra.base.ILangExtension;
@@ -57,6 +59,7 @@
import org.apache.hyracks.api.application.ICCServiceContext;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.exceptions.HyracksException;
+import org.apache.hyracks.api.exceptions.Warning;
import org.apache.hyracks.control.cc.ClusterControllerService;
import org.apache.hyracks.util.LogRedactionUtil;
import org.apache.logging.log4j.Level;
@@ -118,8 +121,10 @@
IStatementExecutorFactory statementExecutorFactory = ccApp.getStatementExecutorFactory();
ExecuteStatementResponseMessage responseMsg = new ExecuteStatementResponseMessage(requestMessageId);
try {
+ Set<Warning> warnings = new HashSet<>();
IParser parser = compilationProvider.getParserFactory().createParser(statementsText);
List<Statement> statements = parser.parse();
+ parser.getWarnings(warnings);
StringWriter outWriter = new StringWriter(256);
PrintWriter outPrinter = new PrintWriter(outWriter);
SessionOutput.ResultDecorator resultPrefix = ResultUtil.createPreResultDecorator();
@@ -138,12 +143,13 @@
new RequestParameters(requestReference, statementsText, null, resultProperties, stats, outMetadata,
clientContextID, optionalParameters, stmtParams, multiStatement);
translator.compileAndExecute(ccApp.getHcc(), requestParameters);
+ translator.getWarnings(warnings);
outPrinter.close();
responseMsg.setResult(outWriter.toString());
responseMsg.setMetadata(outMetadata);
responseMsg.setStats(stats);
responseMsg.setExecutionPlans(translator.getExecutionPlans());
- responseMsg.setWarnings(translator.getWarnings());
+ responseMsg.setWarnings(warnings);
} catch (AlgebricksException | HyracksException | TokenMgrError
| org.apache.asterix.aqlplus.parser.TokenMgrError pe) {
// we trust that "our" exceptions are serializable and have a comprehensible error message
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementResponseMessage.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementResponseMessage.java
index 7a7661d..58898cf 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementResponseMessage.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementResponseMessage.java
@@ -19,7 +19,7 @@
package org.apache.asterix.app.message;
-import java.util.List;
+import java.util.Collection;
import org.apache.asterix.common.api.INcApplicationContext;
import org.apache.asterix.common.messaging.api.INcAddressedMessage;
@@ -45,7 +45,7 @@
private ExecutionPlans executionPlans;
- private List<Warning> warnings;
+ private Collection<Warning> warnings;
public ExecuteStatementResponseMessage(long requestMessageId) {
this.requestMessageId = requestMessageId;
@@ -100,11 +100,11 @@
this.executionPlans = executionPlans;
}
- public List<Warning> getWarnings() {
+ public Collection<Warning> getWarnings() {
return warnings;
}
- public void setWarnings(List<Warning> warnings) {
+ public void setWarnings(Collection<Warning> warnings) {
this.warnings = warnings;
}
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 37c7d82..e1247bd 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
@@ -23,6 +23,7 @@
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
@@ -73,6 +74,7 @@
import org.apache.asterix.common.exceptions.ExceptionUtils;
import org.apache.asterix.common.exceptions.MetadataException;
import org.apache.asterix.common.exceptions.RuntimeDataException;
+import org.apache.asterix.common.exceptions.WarningCollector;
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.common.utils.JobUtils;
import org.apache.asterix.common.utils.JobUtils.ProgressState;
@@ -231,7 +233,7 @@
protected final EnumSet<JobFlag> jobFlags = EnumSet.noneOf(JobFlag.class);
protected final IMetadataLockManager lockManager;
protected final IResponsePrinter responsePrinter;
- protected final List<Warning> warnings;
+ protected final WarningCollector warningCollector;
public QueryTranslator(ICcApplicationContext appCtx, List<Statement> statements, SessionOutput output,
ILangCompilationProvider compilationProvider, ExecutorService executorService,
@@ -248,7 +250,7 @@
activeDataverse = MetadataBuiltinEntities.DEFAULT_DATAVERSE;
this.executorService = executorService;
this.responsePrinter = responsePrinter;
- warnings = new ArrayList<>();
+ this.warningCollector = new WarningCollector();
if (appCtx.getServiceContext().getAppConfig().getBoolean(CCConfig.Option.ENFORCE_FRAME_WRITER_PROTOCOL)) {
this.jobFlags.add(JobFlag.ENFORCE_CONTRACT);
}
@@ -1746,7 +1748,7 @@
paramVars.add(new VarIdentifier(v));
}
apiFramework.reWriteQuery(declaredFunctions, metadataProvider, wrappedQuery, sessionOutput, false,
- paramVars);
+ paramVars, warningCollector);
List<List<List<String>>> dependencies = FunctionUtil.getFunctionDependencies(
rewriterFactory.createQueryRewriter(), cfs.getFunctionBodyExpression(), metadataProvider);
@@ -1843,7 +1845,7 @@
loadStmt.getAdapter(), loadStmt.getProperties(), loadStmt.dataIsAlreadySorted());
cls.setSourceLocation(stmt.getSourceLocation());
JobSpecification spec = apiFramework.compileQuery(hcc, metadataProvider, null, 0, null, sessionOutput, cls,
- null, responsePrinter);
+ null, responsePrinter, warningCollector);
afterCompile();
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
bActiveTxn = false;
@@ -1970,12 +1972,12 @@
// Query Rewriting (happens under the same ongoing metadata transaction)
Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
- metadataProvider, query, sessionOutput, true, externalVars.keySet());
+ metadataProvider, query, sessionOutput, true, externalVars.keySet(), warningCollector);
// Query Compilation (happens under the same ongoing metadata transaction)
return apiFramework.compileQuery(clusterInfoCollector, metadataProvider, (Query) rewrittenResult.first,
rewrittenResult.second, stmt == null ? null : stmt.getDatasetName(), sessionOutput, stmt, externalVars,
- responsePrinter);
+ responsePrinter, warningCollector);
}
private JobSpecification rewriteCompileInsertUpsert(IClusterInfoCollector clusterInfoCollector,
@@ -1987,7 +1989,7 @@
// Insert/upsert statement rewriting (happens under the same ongoing metadata transaction)
Pair<IReturningStatement, Integer> rewrittenResult = apiFramework.reWriteQuery(declaredFunctions,
- metadataProvider, insertUpsert, sessionOutput, true, externalVars.keySet());
+ metadataProvider, insertUpsert, sessionOutput, true, externalVars.keySet(), warningCollector);
InsertStatement rewrittenInsertUpsert = (InsertStatement) rewrittenResult.first;
String dataverseName = getActiveDataverse(rewrittenInsertUpsert.getDataverseName());
@@ -2013,7 +2015,8 @@
// Insert/upsert statement compilation (happens under the same ongoing metadata
// transaction)
return apiFramework.compileQuery(clusterInfoCollector, metadataProvider, rewrittenInsertUpsert.getQuery(),
- rewrittenResult.second, datasetName, sessionOutput, clfrqs, externalVars, responsePrinter);
+ rewrittenResult.second, datasetName, sessionOutput, clfrqs, externalVars, responsePrinter,
+ warningCollector);
}
protected void handleCreateFeedStatement(MetadataProvider metadataProvider, Statement stmt) throws Exception {
@@ -2547,7 +2550,7 @@
(org.apache.asterix.api.common.ResultMetadata) controllerService.getResultDirectoryService()
.getResultMetadata(jobId, rsId);
stats.setProcessedObjects(resultMetadata.getProcessedObjects());
- warnings.addAll(resultMetadata.getWarnings());
+ warningCollector.warn(resultMetadata.getWarnings());
}
private void asyncCreateAndRunJob(IHyracksClientConnection hcc, IStatementCompiler compiler, IMetadataLocker locker,
@@ -2922,8 +2925,8 @@
}
@Override
- public List<Warning> getWarnings() {
- return warnings;
+ public void getWarnings(Collection<? super Warning> outWarnings) {
+ warningCollector.getWarnings(outWarnings);
}
/**
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index d05ae3e..220ec38 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -40,6 +40,7 @@
import java.net.URISyntaxException;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
+import java.text.MessageFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -963,7 +964,9 @@
variableCtx, ctx.getType(), testFile, expectedResultFile, actualResultFile, queryCount,
expectedResultFileCtxs.size(), cUnit.getParameter(), ComparisonEnum.TEXT);
if (testCaseCtx.getTestCase().isCheckWarnings()) {
- validateWarnings(extractedResult.getWarnings(), cUnit.getExpectedWarn(), actualWarnCount);
+ boolean expectedSourceLoc = testCaseCtx.isSourceLocationExpected(cUnit);
+ validateWarnings(extractedResult.getWarnings(), cUnit.getExpectedWarn(), actualWarnCount,
+ expectedSourceLoc);
}
break;
case "store":
@@ -2103,16 +2106,22 @@
return extension.endsWith(AQL) ? getEndpoint(Servlets.QUERY_AQL) : getEndpoint(Servlets.QUERY_SERVICE);
}
- private void validateWarnings(List<String> actualWarnings, List<String> expectedWarn, MutableInt actualWarnCount)
- throws Exception {
+ private void validateWarnings(List<String> actualWarnings, List<String> expectedWarn, MutableInt actualWarnCount,
+ boolean expectedSourceLoc) throws Exception {
if (actualWarnCount.getValue() > expectedWarn.size()) {
- throw new IllegalStateException("returned warnings exceeded expected warnings");
+ throw new Exception("returned warnings exceeded expected warnings");
}
- for (String actualWarn : actualWarnings) {
- if (expectedWarn.stream().anyMatch(actualWarn::contains)) {
+ if (actualWarnings != null) {
+ for (String actualWarn : actualWarnings) {
+ if (expectedWarn.stream().noneMatch(actualWarn::contains)) {
+ throw new Exception("unexpected warning was encountered (" + actualWarn + ")");
+ }
+ if (expectedSourceLoc && !containsSourceLocation(actualWarn)) {
+ throw new Exception(MessageFormat.format(
+ "Expected to find source location \"{}, {}\" in warning text: +++++{}+++++",
+ ERR_MSG_SRC_LOC_LINE_REGEX, ERR_MSG_SRC_LOC_COLUMN_REGEX, actualWarn));
+ }
actualWarnCount.increment();
- } else {
- throw new Exception("unexpected warning was encountered (" + actualWarn + ")");
}
}
}
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 0b89981..4f5fe7a 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
@@ -150,7 +150,8 @@
Query query = (Query) st;
IQueryRewriter rewriter = sqlppRewriterFactory.createQueryRewriter();
rewrite(rewriter, functions, query, metadataProvider,
- new LangRewritingContext(query.getVarCounter()));
+ new LangRewritingContext(query.getVarCounter(), w -> {
+ }));
// Tests deep copy and deep equality.
Query copiedQuery = (Query) SqlppRewriteUtil.deepCopy(query);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
new file mode 100644
index 0000000..0c0e667
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.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 : Warning when a GROUP BY hint is recognized,
+ * : but cannot be applied for given aggregate function
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+with ds as (
+ from range(1, 4) r
+ select r % 2 as x, r as y
+)
+
+from ds
+where y < 3
+/*+ hash */ group by x
+select x, array_agg(y) as y
+order by x
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.1.query.sqlpp
new file mode 100644
index 0000000..eb2bfd9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.1.query.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.
+ */
+
+/*
+ * Description : Warning when a GROUP BY hint is not recognized
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+with ds as (
+ from range(1, 4) r
+ select r % 2 as x, r as y
+)
+
+from ds
+/*+ unknown_hint_groupby */ group by x
+select x, sum(y) as y
+order by x
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.2.query.sqlpp
new file mode 100644
index 0000000..3e89bb0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.2.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Warning when a relational expression hint is not recognized
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+from range(1, 4) r
+where r /*+ unknown_hint_relexpr */ < 2
+select value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.3.query.sqlpp
new file mode 100644
index 0000000..ebef6d3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.3.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Warning when a BETWEEN hint is not recognized
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+from range(1, 4) r
+where r /*+ unknown_hint_between */ between 0 and 1
+select value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.4.query.sqlpp
new file mode 100644
index 0000000..c80b17e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.4.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Warning when a function call hint is not recognized
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+from range(1, 4) r
+where /*+ unknown_hint_funcall */ tostring(r) < "2"
+select value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.adm
new file mode 100644
index 0000000..9c866a3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.adm
@@ -0,0 +1,2 @@
+{ "x": 0, "y": [ 2 ] }
+{ "x": 1, "y": [ 1 ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.1.adm
new file mode 100644
index 0000000..60bff22
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.1.adm
@@ -0,0 +1,2 @@
+{ "x": 0, "y": 6 }
+{ "x": 1, "y": 4 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.2.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.2.adm
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.3.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.3.adm
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.4.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.4.adm
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 5b2cacf..c297b58 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -12344,11 +12344,26 @@
</test-group>
<test-group name="warnings">
<test-case FilePath="warnings" check-warnings="true">
+ <compilation-unit name="inapplicable-hint-warning">
+ <output-dir compare="Text">inapplicable-hint-warning</output-dir>
+ <expected-warn>HYR10006: Could not apply Group By hint: hash</expected-warn>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="warnings" check-warnings="true">
<compilation-unit name="min-max-incompatible-types">
<output-dir compare="Text">min-max-incompatible-types</output-dir>
<expected-warn>ASX0003: Type incompatibility: function min/max gets incompatible input values: bigint and string</expected-warn>
<expected-warn>ASX0004: Unsupported type: min/max cannot process input type object</expected-warn>
</compilation-unit>
</test-case>
+ <test-case FilePath="warnings" check-warnings="true">
+ <compilation-unit name="unknown-hint-warning">
+ <output-dir compare="Text">unknown-hint-warning</output-dir>
+ <expected-warn>ASX1107: Unknown hint: unknown_hint_groupby. Supported hints are: hash</expected-warn>
+ <expected-warn>ASX1107: Unknown hint: unknown_hint_relexpr. Supported hints are: indexnl, skip-index, bcast</expected-warn>
+ <expected-warn>ASX1107: Unknown hint: unknown_hint_between. Supported hints are: indexnl, skip-index</expected-warn>
+ <expected-warn>ASX1107: Unknown hint: unknown_hint_funcall. Supported hints are: indexnl, skip-index</expected-warn>
+ </compilation-unit>
+ </test-case>
</test-group>
</test-suite>
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 dc67f7e..67f0170 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
@@ -187,6 +187,7 @@
public static final int INVALID_FUNCTION_MODIFIER = 1104;
public static final int OPERATION_NOT_SUPPORTED_ON_PRIMARY_INDEX = 1105;
public static final int EXPECTED_CONSTANT_VALUE = 1106;
+ public static final int UNKNOWN_HINT = 1107;
// Feed errors
public static final int DATAFLOW_ILLEGAL_STATE = 3001;
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningCollector.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningCollector.java
new file mode 100644
index 0000000..2f0af3b
--- /dev/null
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningCollector.java
@@ -0,0 +1,49 @@
+/*
+ * 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.common.exceptions;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.hyracks.api.exceptions.IWarningCollector;
+import org.apache.hyracks.api.exceptions.Warning;
+
+public final class WarningCollector implements IWarningCollector {
+
+ private final Set<Warning> warnings = new HashSet<>();
+
+ public void clear() {
+ warnings.clear();
+ }
+
+ @Override
+ public void warn(Warning warning) {
+ this.warnings.add(warning);
+ }
+
+ public void warn(Collection<Warning> warnings) {
+ this.warnings.addAll(warnings);
+ }
+
+ public void getWarnings(Collection<? super Warning> outWarnings) {
+ outWarnings.addAll(warnings);
+ }
+}
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/WarningUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningUtil.java
similarity index 93%
rename from asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/WarningUtil.java
rename to asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningUtil.java
index e52df21..3ea3877 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/WarningUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningUtil.java
@@ -16,11 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.asterix.common.utils;
+package org.apache.asterix.common.exceptions;
import java.io.Serializable;
-import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.SourceLocation;
import org.apache.hyracks.api.exceptions.Warning;
import org.apache.hyracks.api.util.ErrorMessageUtil;
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 0478815..8bac58c 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -182,6 +182,7 @@
1104 = Invalid modifier %1$s for function %2$s
1105 = Operation not supported on primary index %1$s
1106 = Expected constant value
+1107 = Unknown hint: %1$s. Supported hints are: %2$s
# Feed Errors
3001 = Illegal state.
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/AQLVariableSubstitutionUtil.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/AQLVariableSubstitutionUtil.java
index f19afac..16e081f 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/AQLVariableSubstitutionUtil.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/AQLVariableSubstitutionUtil.java
@@ -33,7 +33,8 @@
public static ILangExpression substituteVariable(ILangExpression expression,
Map<VariableExpr, Expression> varExprMap) throws CompilationException {
AQLCloneAndSubstituteVariablesVisitor visitor =
- new AQLCloneAndSubstituteVariablesVisitor(new LangRewritingContext(0));
+ new AQLCloneAndSubstituteVariablesVisitor(new LangRewritingContext(0, w -> {
+ }));
VariableSubstitutionEnvironment env = new VariableSubstitutionEnvironment(varExprMap);
return expression.accept(visitor, env).first;
}
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 b1287224..2f9eb9f 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
@@ -18,12 +18,19 @@
*/
package org.apache.asterix.lang.common.base;
+import java.util.Collection;
import java.util.List;
import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.hyracks.api.exceptions.Warning;
public interface IParser {
- public List<Statement> parse() throws CompilationException;
+ List<Statement> parse() throws CompilationException;
+ /**
+ * Gets the warnings generated during parsing
+ */
+ default void getWarnings(Collection<? super Warning> outWarnings) {
+ }
}
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 dbcb358..563e07e 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
@@ -23,14 +23,17 @@
import org.apache.asterix.lang.common.struct.VarIdentifier;
import org.apache.hyracks.algebricks.core.algebra.base.Counter;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
public final class LangRewritingContext {
+ private final IWarningCollector warningCollector;
private Counter varCounter;
private int systemVarCounter = 1;
private Map<Integer, VarIdentifier> oldVarIdToNewVarId = new HashMap<>();
- public LangRewritingContext(int varCounter) {
+ public LangRewritingContext(int varCounter, IWarningCollector warningCollector) {
this.varCounter = new Counter(varCounter);
+ this.warningCollector = warningCollector;
}
public Counter getVarCounter() {
@@ -68,4 +71,8 @@
varCounter.inc();
return varCounter.get();
}
+
+ public IWarningCollector getWarningCollector() {
+ return warningCollector;
+ }
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 73c4137..62c041c 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -40,8 +40,11 @@
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -65,6 +68,8 @@
import org.apache.asterix.common.config.DatasetConfig.IndexType;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.WarningCollector;
+import org.apache.asterix.common.exceptions.WarningUtil;
import org.apache.asterix.common.functions.FunctionConstants;
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.lang.common.base.AbstractClause;
@@ -177,6 +182,7 @@
import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.commons.lang3.StringUtils;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -184,6 +190,7 @@
import org.apache.hyracks.algebricks.core.algebra.expressions.IndexedNLJoinExpressionAnnotation;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.api.exceptions.Warning;
import org.apache.hyracks.util.LogRedactionUtil;
class SQLPPParser extends ScopeChecker implements IParser {
@@ -236,6 +243,8 @@
private int externalVarCounter;
+ private final WarningCollector warningCollector = new WarningCollector();
+
private static class IndexParams {
public IndexType type;
public int gramLength;
@@ -252,6 +261,7 @@
public String function;
public String hint;
public SourceLocation sourceLoc;
+ public SourceLocation hintSourceLoc;
}
private String getHint(Token t) {
@@ -331,6 +341,7 @@
}
public List<Statement> parse() throws CompilationException {
+ warningCollector.clear();
try {
return Statement();
} catch (Error e) {
@@ -345,6 +356,11 @@
}
}
+ @Override
+ public void getWarnings(Collection<? super Warning> outWarnings) {
+ warningCollector.getWarnings(outWarnings);
+ }
+
protected String getMessage(ParseException pe) {
Token currentToken = pe.currentToken;
if (currentToken == null) {
@@ -421,6 +437,11 @@
private boolean laIdentifier(String image) {
return laIdentifier(1, image);
}
+
+ private void warnUnknownHint(String actualHint, SourceLocation sourceLoc, String... expectedHints) {
+ warningCollector.warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.UNKNOWN_HINT, actualHint,
+ StringUtils.join(expectedHints, ", ")));
+ }
}
PARSER_END(SQLPPParser)
@@ -1647,6 +1668,7 @@
FunctionName result = new FunctionName();
result.hint = getHint(token);
result.sourceLoc = getSourceLocation(token);
+ result.hintSourceLoc = getSourceLocation(getHintToken(token));
}
( <DOT> second = Identifier()
{
@@ -2018,6 +2040,10 @@
annotation = SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE;
} else if (mhint.equals(BROADCAST_JOIN_HINT)) {
broadcast = true;
+ } else {
+ warnUnknownHint(mhint, getSourceLocation(getHintToken(token)),
+ INDEXED_NESTED_LOOP_JOIN_HINT, SKIP_SECONDARY_INDEX_SEARCH_HINT, BROADCAST_JOIN_HINT
+ );
}
}
@@ -2074,6 +2100,10 @@
annotation = IndexedNLJoinExpressionAnnotation.INSTANCE;
} else if (mhint.equals(SKIP_SECONDARY_INDEX_SEARCH_HINT)) {
annotation = SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE;
+ } else {
+ warnUnknownHint(mhint, getSourceLocation(getHintToken(token)),
+ INDEXED_NESTED_LOOP_JOIN_HINT, SKIP_SECONDARY_INDEX_SEARCH_HINT
+ );
}
}
String operator = token.image.toLowerCase();
@@ -2716,15 +2746,11 @@
Expression tmp = null;
int arity = 0;
FunctionName funcName = null;
- String hint = null;
boolean star = false;
boolean distinct = false;
}
{
funcName = FunctionName()
- {
- hint = funcName.hint;
- }
<LEFTPAREN> (
( <DISTINCT> { distinct = true; } )?
( tmp = Expression() | <MUL> { star = true; } )
@@ -2758,11 +2784,16 @@
signature = new FunctionSignature(funcName.dataverse, fqFunctionName, arity);
}
callExpr = FunctionMapUtil.normalizedListInputFunctions(new CallExpr(signature,argList));
+ String hint = funcName.hint;
if (hint != null) {
if (hint.startsWith(INDEXED_NESTED_LOOP_JOIN_HINT)) {
callExpr.addHint(IndexedNLJoinExpressionAnnotation.INSTANCE);
} else if (hint.startsWith(SKIP_SECONDARY_INDEX_SEARCH_HINT)) {
callExpr.addHint(SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE);
+ } else {
+ warnUnknownHint(hint, funcName.hintSourceLoc,
+ INDEXED_NESTED_LOOP_JOIN_HINT, SKIP_SECONDARY_INDEX_SEARCH_HINT
+ );
}
}
callExpr.setSourceLocation(funcName.sourceLoc);
@@ -3429,8 +3460,7 @@
int numTuples = Integer.parseInt(splits[2]);
oc.setNumFrames(numFrames);
oc.setNumTuples(numTuples);
- }
- if (hint.startsWith(RANGE_HINT)) {
+ } else if (hint.startsWith(RANGE_HINT)) {
try {
oc.setRangeMap(RangeMapBuilder.parseHint(createNewParser(hint.substring(RANGE_HINT.length()))));
} catch (CompilationException e) {
@@ -3491,8 +3521,12 @@
{
startToken = token;
String hint = getHint(token);
- if (hint != null && hint.equals(HASH_GROUP_BY_HINT)) {
- gbc.setHashGroupByHint(true);
+ if (hint != null) {
+ if (hint.equals(HASH_GROUP_BY_HINT)) {
+ gbc.setHashGroupByHint(true);
+ } else {
+ warnUnknownHint(hint, getSourceLocation(getHintToken(token)), HASH_GROUP_BY_HINT);
+ }
}
}
<BY> (
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/AbstractMinMaxAggregateFunction.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/AbstractMinMaxAggregateFunction.java
index 463a676..f0caa09 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/AbstractMinMaxAggregateFunction.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/AbstractMinMaxAggregateFunction.java
@@ -21,7 +21,7 @@
import java.io.IOException;
import org.apache.asterix.common.exceptions.ErrorCode;
-import org.apache.asterix.common.utils.WarningUtil;
+import org.apache.asterix.common.exceptions.WarningUtil;
import org.apache.asterix.dataflow.data.common.ILogicalBinaryComparator;
import org.apache.asterix.dataflow.data.nontagged.comparators.ComparatorUtil;
import org.apache.asterix.om.types.ATypeTag;
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
index deed53d..a95e813 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
@@ -44,6 +44,7 @@
import org.apache.hyracks.algebricks.data.ITypeTraitProvider;
import org.apache.hyracks.api.dataflow.value.IMissingWriterFactory;
import org.apache.hyracks.api.dataflow.value.IPredicateEvaluatorFactoryProvider;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
public abstract class AbstractCompilerFactoryBuilder {
@@ -69,6 +70,7 @@
protected IMergeAggregationExpressionFactory mergeAggregationExpressionFactory;
protected PhysicalOptimizationConfig physicalOptimizationConfig = new PhysicalOptimizationConfig();
protected AlgebricksAbsolutePartitionConstraint clusterLocations;
+ protected IWarningCollector warningCollector;
public abstract ICompilerFactory create();
@@ -242,4 +244,11 @@
return conflictingTypeResolver;
}
+ public void setWarningCollector(IWarningCollector warningCollector) {
+ this.warningCollector = warningCollector;
+ }
+
+ public IWarningCollector getWarningCollector() {
+ return warningCollector;
+ }
}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
index a25e2a3..6aed2d6 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
@@ -36,6 +36,7 @@
import org.apache.hyracks.algebricks.core.rewriter.base.HeuristicOptimizer;
import org.apache.hyracks.algebricks.core.rewriter.base.IOptimizationContextFactory;
import org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.api.job.IJobletEventListenerFactory;
import org.apache.hyracks.api.job.JobSpecification;
@@ -54,11 +55,12 @@
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer missableTypeComputer,
IConflictingTypeResolver conflictingTypeResolver, PhysicalOptimizationConfig physicalOptimizationConfig,
- AlgebricksPartitionConstraint clusterLocations) {
+ AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector) {
LogicalOperatorPrettyPrintVisitor prettyPrintVisitor = new LogicalOperatorPrettyPrintVisitor();
return new AlgebricksOptimizationContext(varCounter, expressionEvalSizeComputer,
mergeAggregationExpressionFactory, expressionTypeComputer, missableTypeComputer,
- conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, prettyPrintVisitor);
+ conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, prettyPrintVisitor,
+ warningCollector);
}
}
@@ -80,7 +82,8 @@
int varCounter) {
final IOptimizationContext oc = optCtxFactory.createOptimizationContext(varCounter,
expressionEvalSizeComputer, mergeAggregationExpressionFactory, expressionTypeComputer,
- missableTypeComputer, conflictingTypeResolver, physicalOptimizationConfig, clusterLocations);
+ missableTypeComputer, conflictingTypeResolver, physicalOptimizationConfig, clusterLocations,
+ warningCollector);
oc.setMetadataDeclarations(metadata);
final HeuristicOptimizer opt = new HeuristicOptimizer(plan, logicalRewrites, physicalRewrites, oc);
return new ICompiler() {
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java
index ea486f1..c31cb88 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java
@@ -32,6 +32,7 @@
import org.apache.hyracks.algebricks.core.algebra.typing.ITypingContext;
import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
import org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
public interface IOptimizationContext extends ITypingContext, IVariableContext {
@@ -84,4 +85,6 @@
public AbstractLogicalOperatorPrettyPrintVisitor getPrettyPrintVisitor();
public INodeDomain getComputationNodeDomain();
+
+ public IWarningCollector getWarningCollector();
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
index 8c994e7..eb398e6 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
@@ -43,6 +43,7 @@
import org.apache.hyracks.algebricks.core.algebra.properties.FunctionalDependency;
import org.apache.hyracks.algebricks.core.algebra.properties.ILogicalPropertiesVector;
import org.apache.hyracks.algebricks.core.algebra.properties.INodeDomain;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
/**
* The Algebricks default implementation for IOptimizationContext.
@@ -87,13 +88,14 @@
private final INodeDomain defaultNodeDomain;
private final AbstractLogicalOperatorPrettyPrintVisitor prettyPrintVisitor;
private final IConflictingTypeResolver conflictingTypeResovler;
+ private final IWarningCollector warningCollector;
public AlgebricksOptimizationContext(int varCounter, IExpressionEvalSizeComputer expressionEvalSizeComputer,
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer nullableTypeComputer,
IConflictingTypeResolver conflictingTypeResovler, PhysicalOptimizationConfig physicalOptimizationConfig,
AlgebricksPartitionConstraint clusterLocations,
- AbstractLogicalOperatorPrettyPrintVisitor prettyPrintVisitor) {
+ AbstractLogicalOperatorPrettyPrintVisitor prettyPrintVisitor, IWarningCollector warningCollector) {
this.varCounter = varCounter;
this.expressionEvalSizeComputer = expressionEvalSizeComputer;
this.mergeAggregationExpressionFactory = mergeAggregationExpressionFactory;
@@ -103,6 +105,7 @@
this.defaultNodeDomain = new DefaultNodeGroupDomain(clusterLocations);
this.prettyPrintVisitor = prettyPrintVisitor;
this.conflictingTypeResovler = conflictingTypeResovler;
+ this.warningCollector = warningCollector;
}
@Override
@@ -329,4 +332,9 @@
public IConflictingTypeResolver getConflictingTypeResolver() {
return conflictingTypeResovler;
}
+
+ @Override
+ public IWarningCollector getWarningCollector() {
+ return warningCollector;
+ }
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java
index 6ceed1e..1c41e9a 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java
@@ -25,6 +25,7 @@
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
import org.apache.hyracks.algebricks.core.algebra.expressions.IMergeAggregationExpressionFactory;
import org.apache.hyracks.algebricks.core.algebra.expressions.IMissableTypeComputer;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
public interface IOptimizationContextFactory {
public IOptimizationContext createOptimizationContext(int varCounter,
@@ -32,5 +33,5 @@
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer missableTypeComputer,
IConflictingTypeResolver conflictintTypeResolver, PhysicalOptimizationConfig physicalOptimizationConfig,
- AlgebricksPartitionConstraint clusterLocations);
+ AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector);
}
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/SetAlgebricksPhysicalOperatorsRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/SetAlgebricksPhysicalOperatorsRule.java
index bc853f0..4795233 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/SetAlgebricksPhysicalOperatorsRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/SetAlgebricksPhysicalOperatorsRule.java
@@ -122,6 +122,7 @@
import org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig;
import org.apache.hyracks.algebricks.rewriter.util.JoinUtils;
import org.apache.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.Warning;
public class SetAlgebricksPhysicalOperatorsRule implements IAlgebraicRewriteRule {
@@ -218,6 +219,9 @@
ExternalGroupByPOperator extGby = createExternalGroupByPOperator(gby);
if (extGby != null) {
return extGby;
+ } else if (gby.getSourceLocation() != null) {
+ context.getWarningCollector().warn(Warning.forHyracks(gby.getSourceLocation(),
+ ErrorCode.INAPPLICABLE_HINT, "Group By", "hash"));
}
}
}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
index a31aef2..4d6dc7d 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
@@ -163,6 +163,7 @@
public static final int DESCRIPTOR_GENERATION_ERROR = 10003;
public static final int EXPR_NOT_NORMALIZED = 10004;
public static final int OPERATOR_NOT_IMPLEMENTED = 10005;
+ public static final int INAPPLICABLE_HINT = 10006;
private static class Holder {
private static final Map<Integer, String> errorMessageMap;
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IWarningCollector.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IWarningCollector.java
new file mode 100644
index 0000000..3ee9abb
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IWarningCollector.java
@@ -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.
+ */
+
+package org.apache.hyracks.api.exceptions;
+
+@FunctionalInterface
+public interface IWarningCollector {
+ void warn(Warning warning);
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
index 8e3b85e..f73f130 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
@@ -145,3 +145,4 @@
10003 = Could not generate operator descriptor for operator %1$s
10004 = Expression has not been normalized
10005 = Operator is not implemented: %1$s
+10006 = Could not apply %1$s hint: %2$s