This is an automated email from the ASF dual-hosted git repository.

dlych pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 1f6a6e3  [NO ISSUE][COMP] Add support for compiler warnings
1f6a6e3 is described below

commit 1f6a6e3ece8cc19c555a410efbe71c5152b2874c
Author: Dmitry Lychagin <[email protected]>
AuthorDate: Tue Jul 2 11:59:53 2019 -0700

    [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 <[email protected]>
    Tested-by: Jenkins <[email protected]>
    Integration-Tests: Jenkins <[email protected]>
    Reviewed-by: Dmitry Lychagin <[email protected]>
    Reviewed-by: Murtadha Hubail <[email protected]>
---
 .../optimizer/base/AsterixOptimizationContext.java |  6 ++-
 .../asterix/translator/IStatementExecutor.java     |  7 ++-
 .../apache/asterix/api/common/APIFramework.java    | 17 +++++---
 .../api/http/server/QueryServiceServlet.java       |  3 +-
 .../message/ExecuteStatementRequestMessage.java    |  8 +++-
 .../message/ExecuteStatementResponseMessage.java   |  8 ++--
 .../asterix/app/translator/QueryTranslator.java    | 25 ++++++-----
 .../apache/asterix/test/common/TestExecutor.java   | 25 +++++++----
 .../asterix/test/sqlpp/ParserTestExecutor.java     |  3 +-
 .../inapplicable-hint-warning.1.query.sqlpp}       | 22 ++++++----
 .../unknown-hint-warning.1.query.sqlpp}            | 20 +++++----
 .../unknown-hint-warning.2.query.sqlpp}            | 16 +++----
 .../unknown-hint-warning.3.query.sqlpp}            | 16 +++----
 .../unknown-hint-warning.4.query.sqlpp}            | 16 +++----
 .../inapplicable-hint-warning.1.adm                |  2 +
 .../unknown-hint-warning.1.adm                     |  2 +
 .../unknown-hint-warning.2.adm                     |  1 +
 .../unknown-hint-warning.3.adm                     |  1 +
 .../unknown-hint-warning.4.adm                     |  1 +
 .../test/resources/runtimets/testsuite_sqlpp.xml   | 15 +++++++
 .../asterix/common/exceptions/ErrorCode.java       |  1 +
 .../common/exceptions/WarningCollector.java}       | 30 ++++++++++---
 .../common/{utils => exceptions}/WarningUtil.java  |  3 +-
 .../src/main/resources/asx_errormsg/en.properties  |  1 +
 .../lang/aql/util/AQLVariableSubstitutionUtil.java |  3 +-
 .../apache/asterix/lang/common/base/IParser.java   |  9 +++-
 .../lang/common/rewrites/LangRewritingContext.java |  9 +++-
 .../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj    | 50 ++++++++++++++++++----
 .../std/AbstractMinMaxAggregateFunction.java       |  2 +-
 .../api/AbstractCompilerFactoryBuilder.java        |  9 ++++
 .../api/HeuristicCompilerFactoryBuilder.java       |  9 ++--
 .../core/algebra/base/IOptimizationContext.java    |  3 ++
 .../base/AlgebricksOptimizationContext.java        | 10 ++++-
 .../rewriter/base/IOptimizationContextFactory.java |  3 +-
 .../rules/SetAlgebricksPhysicalOperatorsRule.java  |  4 ++
 .../apache/hyracks/api/exceptions/ErrorCode.java   |  1 +
 .../hyracks/api/exceptions/IWarningCollector.java  | 12 ++----
 .../src/main/resources/errormsg/en.properties      |  1 +
 38 files changed, 260 insertions(+), 114 deletions(-)

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.expressions.IMissableTypeCompu
 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 @@ public final class AsterixOptimizationContext extends 
AlgebricksOptimizationCont
             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 @@ package org.apache.asterix.translator;
 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 @@ public interface IStatementExecutor {
     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.client.NodeControllerInfo;
 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 @@ public class APIFramework {
                 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 @@ public class APIFramework {
             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 @@ public class APIFramework {
         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 @@ public class QueryServiceServlet extends 
AbstractQueryApiServlet {
         }
         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 @@ public class QueryServiceServlet extends 
AbstractQueryApiServlet {
                 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 @@ package org.apache.asterix.app.message;
 
 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.algebricks.common.exceptions.AlgebricksException;
 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 @@ public final class ExecuteStatementRequestMessage 
implements ICcAddressedMessage
         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 @@ public final class ExecuteStatementRequestMessage 
implements ICcAddressedMessage
                     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 @@ public final class ExecuteStatementResponseMessage implements 
INcAddressedMessag
 
     private ExecutionPlans executionPlans;
 
-    private List<Warning> warnings;
+    private Collection<Warning> warnings;
 
     public ExecuteStatementResponseMessage(long requestMessageId) {
         this.requestMessageId = requestMessageId;
@@ -100,11 +100,11 @@ public final class ExecuteStatementResponseMessage 
implements INcAddressedMessag
         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.FileInputStream;
 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.ErrorCode;
 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 @@ public class QueryTranslator extends AbstractLangTranslator 
implements IStatemen
     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 @@ public class QueryTranslator extends AbstractLangTranslator 
implements IStatemen
         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 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
                 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 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
                             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 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
 
         // 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 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
 
         // 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 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
         // 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 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
                 (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 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
     }
 
     @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.URI;
 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 @@ public class TestExecutor {
                         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 @@ public class TestExecutor {
         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 @@ public class ParserTestExecutor extends TestExecutor {
                     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-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
similarity index 70%
copy from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
index b128722..0c0e667 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
@@ -16,14 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.lang.common.base;
 
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-
-public interface IParser {
+/*
+ * Description  : Warning when a GROUP BY hint is recognized,
+ *              : but cannot be applied for given aggregate function
+ * Expected     : SUCCESS (with ASX1107 warning)
+ */
 
-    public List<Statement> parse() throws CompilationException;
+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-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.1.query.sqlpp
similarity index 75%
copy from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.1.query.sqlpp
index b128722..eb2bfd9 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.1.query.sqlpp
@@ -16,14 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.lang.common.base;
 
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-
-public interface IParser {
+/*
+ * Description  : Warning when a GROUP BY hint is not recognized
+ * Expected     : SUCCESS (with ASX1107 warning)
+ */
 
-    public List<Statement> parse() throws CompilationException;
+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-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.2.query.sqlpp
similarity index 77%
copy from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.2.query.sqlpp
index b128722..3e89bb0 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.2.query.sqlpp
@@ -16,14 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.lang.common.base;
 
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-
-public interface IParser {
-
-    public List<Statement> parse() throws CompilationException;
+/*
+ * 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-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.3.query.sqlpp
similarity index 77%
copy from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.3.query.sqlpp
index b128722..ebef6d3 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.3.query.sqlpp
@@ -16,14 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.lang.common.base;
 
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-
-public interface IParser {
-
-    public List<Statement> parse() throws CompilationException;
+/*
+ * 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-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.4.query.sqlpp
similarity index 77%
copy from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.4.query.sqlpp
index b128722..c80b17e 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.4.query.sqlpp
@@ -16,14 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.lang.common.base;
 
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-
-public interface IParser {
-
-    public List<Statement> parse() throws CompilationException;
+/*
+ * 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 class ErrorCode {
     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-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningCollector.java
similarity index 52%
copy from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
copy to 
asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningCollector.java
index b128722..2f0af3b 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/WarningCollector.java
@@ -16,14 +16,34 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.lang.common.base;
 
-import java.util.List;
+package org.apache.asterix.common.exceptions;
 
-import org.apache.asterix.common.exceptions.CompilationException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
-public interface IParser {
+import org.apache.hyracks.api.exceptions.IWarningCollector;
+import org.apache.hyracks.api.exceptions.Warning;
 
-    public List<Statement> parse() throws CompilationException;
+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 class AQLVariableSubstitutionUtil {
     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 b128722..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 java.util.Map;
 
 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 @@ public final class LangRewritingContext {
         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.InputStreamReader;
 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.DatasetType;
 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.ExpressionToVariableUtil;
 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.IExpressionAnnotat
 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 @@ class SQLPPParser extends ScopeChecker implements IParser {
 
     private int externalVarCounter;
 
+    private final WarningCollector warningCollector = new WarningCollector();
+
     private static class IndexParams {
       public IndexType type;
       public int gramLength;
@@ -252,6 +261,7 @@ class SQLPPParser extends ScopeChecker implements IParser {
        public String function;
        public String hint;
        public SourceLocation sourceLoc;
+       public SourceLocation hintSourceLoc;
     }
 
     private String getHint(Token t) {
@@ -331,6 +341,7 @@ class SQLPPParser extends ScopeChecker implements IParser {
     }
 
     public List<Statement> parse() throws CompilationException {
+        warningCollector.clear();
         try {
             return Statement();
         } catch (Error e) {
@@ -345,6 +356,11 @@ class SQLPPParser extends ScopeChecker implements IParser {
         }
     }
 
+    @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 @@ class SQLPPParser extends ScopeChecker implements IParser {
     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 FunctionName() throws ParseException:
     FunctionName result = new FunctionName();
     result.hint = getHint(token);
     result.sourceLoc = getSourceLocation(token);
+    result.hintSourceLoc = getSourceLocation(getHintToken(token));
   }
   ( <DOT> second = Identifier()
     {
@@ -2018,6 +2040,10 @@ Expression RelExpr() throws ParseException:
                 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 @@ Expression BetweenExpr() throws ParseException:
                 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 FunctionCallExpr() throws ParseException:
   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 @@ Expression FunctionCallExpr() throws ParseException:
         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 @@ OrderbyClause OrderbyClause() throws ParseException :
             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 @@ GroupbyClause GroupbyClause()throws ParseException :
       {
          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 @@ package org.apache.asterix.runtime.aggregates.std;
 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.ISerializerDeserializerProvider;
 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 @@ public abstract class AbstractCompilerFactoryBuilder {
     protected IMergeAggregationExpressionFactory 
mergeAggregationExpressionFactory;
     protected PhysicalOptimizationConfig physicalOptimizationConfig = new 
PhysicalOptimizationConfig();
     protected AlgebricksAbsolutePartitionConstraint clusterLocations;
+    protected IWarningCollector warningCollector;
 
     public abstract ICompilerFactory create();
 
@@ -242,4 +244,11 @@ public abstract class AbstractCompilerFactoryBuilder {
         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.AlgebricksOptimizationCo
 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 @@ public class HeuristicCompilerFactoryBuilder extends 
AbstractCompilerFactoryBuil
                 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 @@ public class HeuristicCompilerFactoryBuilder extends 
AbstractCompilerFactoryBuil
                     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.properties.INodeDomain;
 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 interface IOptimizationContext extends ITypingContext, 
IVariableContext {
     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.DefaultNodeGroupDom
 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 @@ public class AlgebricksOptimizationContext implements 
IOptimizationContext {
     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 @@ public class AlgebricksOptimizationContext implements 
IOptimizationContext {
         this.defaultNodeDomain = new DefaultNodeGroupDomain(clusterLocations);
         this.prettyPrintVisitor = prettyPrintVisitor;
         this.conflictingTypeResovler = conflictingTypeResovler;
+        this.warningCollector = warningCollector;
     }
 
     @Override
@@ -329,4 +332,9 @@ public class AlgebricksOptimizationContext implements 
IOptimizationContext {
     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.IExpressionEvalSiz
 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 @@ public interface IOptimizationContextFactory {
             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.IAlgebraicRewriteRule;
 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 @@ public class SetAlgebricksPhysicalOperatorsRule implements 
IAlgebraicRewriteRule
                     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 class ErrorCode {
     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/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IWarningCollector.java
similarity index 78%
copy from 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
copy to 
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IWarningCollector.java
index b128722..3ee9abb 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IParser.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/IWarningCollector.java
@@ -16,14 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.lang.common.base;
 
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-
-public interface IParser {
-
-    public List<Statement> parse() throws CompilationException;
+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

Reply via email to