diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index 176d36f..cad937d 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -1606,6 +1606,8 @@ private static void populateLlapDaemonVarsSet(Set llapDaemonVarsSetLocal HIVESAMPLINGNUMBERFORORDERBY("hive.optimize.sampling.orderby.number", 1000, "Total number of samples to be obtained."), HIVESAMPLINGPERCENTFORORDERBY("hive.optimize.sampling.orderby.percent", 0.1f, new RatioValidator(), "Probability with which a row will be chosen."), + HIVE_CHECK_ORDERBY_IN_SUBQUERY("hive.check.orderby.in.subquery", true, + "If set to true, disallows sub-queries/views containing order by or sort by without limit"), HIVEOPTIMIZEDISTINCTREWRITE("hive.optimize.distinct.rewrite", true, "When applicable this " + "optimization rewrites distinct aggregates from a single stage to multi-stage " + "aggregation. This may not be optimal in all cases. Ideally, whether to trigger it or " diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java index d514644..4311231 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -11247,6 +11247,39 @@ Operator genOPTree(ASTNode ast, PlannerContext plannerCtx) throws SemanticExcept return genPlan(qb); } + private void checkOBInSubQuery(QBExpr qbExpr) throws SemanticException { + if (qbExpr == null) { + return; + } + + if (qbExpr.getOpcode() == QBExpr.Opcode.NULLOP) { + QB subQB = qbExpr.getQB(); + QBParseInfo parseInfo = subQB.getParseInfo(); + String alias = qbExpr.getAlias(); + Map destToOrderBy = parseInfo.getDestToOrderBy(); + Map destToSortBy = parseInfo.getDestToSortBy(); + final String errMsg = "Order/Sort by without limit is not allowed in subquery or view: " + + alias + ", as it's pointless and bad for performance."; + if (destToOrderBy != null) { + for (String dest : destToOrderBy.keySet()) { + if (parseInfo.getDestLimit(dest) == null) { + throw new SemanticException(errMsg); + } + } + } + if (destToSortBy != null) { + for (String dest : destToSortBy.keySet()) { + if (parseInfo.getDestLimit(dest) == null) { + throw new SemanticException(errMsg); + } + } + } + } else { + checkOBInSubQuery(qbExpr.getQBExpr1()); + checkOBInSubQuery(qbExpr.getQBExpr2()); + } + } + void analyzeInternal(ASTNode ast, PlannerContext plannerCtx) throws SemanticException { // 1. Generate Resolved Parse tree from syntax tree LOG.info("Starting Semantic Analysis"); @@ -11256,6 +11289,12 @@ void analyzeInternal(ASTNode ast, PlannerContext plannerCtx) throws SemanticExce return; } + if (HiveConf.getBoolVar(conf, ConfVars.HIVE_CHECK_ORDERBY_IN_SUBQUERY)) { + for (String alias : qb.getSubqAliases()) { + checkOBInSubQuery(qb.getSubqForAlias(alias)); + } + } + // 2. Gen OP Tree from resolved Parse Tree Operator sinkOp = genOPTree(ast, plannerCtx);