diff --git ql/src/java/org/apache/hadoop/hive/ql/lib/RuleRegExp.java ql/src/java/org/apache/hadoop/hive/ql/lib/RuleRegExp.java index fd5f133..1e850d6 100644 --- ql/src/java/org/apache/hadoop/hive/ql/lib/RuleRegExp.java +++ ql/src/java/org/apache/hadoop/hive/ql/lib/RuleRegExp.java @@ -19,7 +19,9 @@ package org.apache.hadoop.hive.ql.lib; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.regex.Matcher; @@ -125,6 +127,12 @@ public RuleRegExp(String ruleName, String regExp) { */ private int costPatternWithoutWildCardChar(Stack stack) throws SemanticException { int numElems = (stack != null ? stack.size() : 0); + + // No elements + if (numElems == 0) { + return -1; + } + int patLen = patternWithoutWildCardChar.length(); StringBuilder name = new StringBuilder(patLen + numElems); for (int pos = numElems - 1; pos >= 0; pos--) { @@ -133,9 +141,8 @@ private int costPatternWithoutWildCardChar(Stack stack) throws SemanticExc if (name.length() >= patLen) { if (patternWithoutWildCardChar.contentEquals(name)) { return patLen; - } else { - return -1; } + break; } } return -1; @@ -152,20 +159,54 @@ private int costPatternWithoutWildCardChar(Stack stack) throws SemanticExc */ private int costPatternWithORWildCardChar(Stack stack) throws SemanticException { int numElems = (stack != null ? stack.size() : 0); + + // No elements + if (numElems == 0) { + return -1; + } + + // These DS are used to cache previously created String + Map cachedNames = new HashMap(); + int maxDepth = numElems; + int maxLength = 0; + + // For every pattern for (String pattern : patternORWildChar) { int patLen = pattern.length(); - StringBuilder name = new StringBuilder(patLen + numElems); - for (int pos = numElems - 1; pos >= 0; pos--) { - String nodeName = stack.get(pos).getName() + "%"; - name.insert(0, nodeName); - if (name.length() >= patLen) { - if (pattern.contentEquals(name)) { - return patLen; - } else { + // If the stack has been explored already till that level, + // obtained cached String + if (cachedNames.containsKey(patLen)) { + if (pattern.contentEquals(cachedNames.get(patLen))) { + return patLen; + } + } else if (maxLength >= patLen) { + // We have already explored the stack deep enough, but + // we do not have a matching + continue; + } else { + // We are going to build the name + StringBuilder name = new StringBuilder(patLen + numElems); + if (maxLength != 0) { + name.append(cachedNames.get(maxLength)); + } + for (int pos = maxDepth - 1; pos >= 0; pos--) { + String nodeName = stack.get(pos).getName() + "%"; + name.insert(0, nodeName); + + // We cache the values + cachedNames.put(name.length(), name.toString()); + maxLength = name.length(); + maxDepth--; + + if (name.length() >= patLen) { + if (pattern.contentEquals(name)) { + return patLen; + } break; } } + } } return -1;