diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java index 89e84127a8..2bd7ace6c2 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java @@ -29,6 +29,12 @@ import java.util.Queue; import java.util.Set; import java.util.Stack; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import com.google.common.collect.Lists; import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.Tree; import org.apache.hadoop.hive.common.type.HiveDecimal; @@ -58,6 +64,9 @@ public final class ParseUtils { /** Parses the Hive query. */ private static final Logger LOG = LoggerFactory.getLogger(ParseUtils.class); + private static final int PARSE_TIME_SEC_DEFAULT = 60 * 2; + private static final String PARSING_TIMEOUT_KEY = "parser.timeoutSec"; + public static ASTNode parse(String command) throws ParseException { return parse(command, null); } @@ -69,14 +78,41 @@ public static ASTNode parse(String command, Context ctx) throws ParseException { /** Parses the Hive query. */ public static ASTNode parse( - String command, Context ctx, String viewFullyQualifiedName) throws ParseException { - ParseDriver pd = new ParseDriver(); - ASTNode tree = pd.parse(command, ctx, viewFullyQualifiedName); - tree = findRootNonNullToken(tree); - handleSetColRefs(tree); - return tree; + final String command, final Context ctx, final String viewFullyQualifiedName) throws ParseException { + final ParseDriver pd = new ParseDriver(); + final long timeoutInSec; + if (ctx != null && ctx.getConf() != null) { + timeoutInSec = ctx.getConf().getInt(PARSING_TIMEOUT_KEY, PARSE_TIME_SEC_DEFAULT); + } else { + timeoutInSec = PARSE_TIME_SEC_DEFAULT; + } + final ExecutorService service = Executors.newSingleThreadExecutor(); + try { + ASTNode tree = service.submit(new Callable() { + @Override + public ASTNode call() throws Exception { + return pd.parse(command, ctx, viewFullyQualifiedName); + } + }).get(timeoutInSec, TimeUnit.SECONDS); + tree = findRootNonNullToken(tree); + handleSetColRefs(tree); + return tree; + } catch (Throwable e) { + throw new TimeoutException(Lists.newArrayList()); + } } + static class TimeoutException extends ParseException { + + public TimeoutException(ArrayList errors) { + super(errors); + } + + @Override + public String getMessage() { + return "The query is taking more time to parse!! Please simplify your query (reduce complex nesting statements)"; + } + } /** * Tests whether the parse tree node is a join token. *