You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by ec...@apache.org on 2011/12/27 19:19:44 UTC
svn commit: r1224966 [10/10] - in /incubator/accumulo/branches/1.4: ./
contrib/accumulo_sample/
contrib/accumulo_sample/ingest/src/main/java/aggregator/
contrib/accumulo_sample/ingest/src/main/java/ingest/
contrib/accumulo_sample/ingest/src/test/java/a...
Modified: incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java?rev=1224966&r1=1224965&r2=1224966&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java (original)
+++ incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java Tue Dec 27 18:19:43 2011
@@ -90,741 +90,759 @@ import com.google.common.collect.Multima
*
*/
public class QueryParser implements ParserVisitor {
-
- public static class QueryTerm {
- private boolean negated = false;
- private String operator = null;
- private Object value = null;
- public QueryTerm(boolean negated, String operator,Object value) {
- super();
- this.negated = negated;
- this.operator = operator;
- this.value = value;
- }
- public boolean isNegated() {
- return negated;
- }
- public String getOperator() {
- return operator;
- }
- public Object getValue() {
- return value;
- }
- public void setNegated(boolean negated) {
- this.negated = negated;
- }
- public void setOperator(String operator) {
- this.operator = operator;
- }
- public void setValue(Object value) {
- this.value = value;
- }
- public String toString() {
- StringBuilder buf = new StringBuilder();
- buf.append("negated: ").append(negated).append(", operator: ").append(operator).append(", value: ").append(value);
- return buf.toString();
- }
- }
-
- /**
- * Holder object
- */
- static class ObjectHolder {
- Object object;
- public Object getObject() {
- return object;
- }
- public void setObject(Object object) {
- this.object = object;
- }
- }
-
- static class FunctionResult {
- private List<TermResult> terms = new ArrayList<TermResult>();
-
- public List<TermResult> getTerms() {
- return terms;
- }
- }
-
- /**
- * Holder object for a term (i.e. field name)
- */
- static class TermResult {
- Object value;
- public TermResult(Object value) { this.value = value; }
- }
-
- /**
- * Holder object for a literal (integer, float, string, or null literal) value
- */
- static class LiteralResult {
- Object value;
- public LiteralResult(Object value) { this.value = value; }
- }
-
- /**
- * Object used to store context information as the AST is being iterated over.
- */
- static class EvaluationContext {
- boolean inOrContext = false;
- boolean inNotContext = false;
- boolean inAndContext = false;
- }
-
- /**
- * Object to store information from previously parsed queries.
- */
- private static class CacheEntry {
- private Set<String> negatedTerms = null;
- private Set<String> andTerms = null;
- private Set<String> orTerms = null;
- private Set<Object> literals = null;
- private Multimap<String,QueryTerm> terms = null;
- private ASTJexlScript rootNode = null;
- private TreeNode tree = null;
- public CacheEntry(Set<String> negatedTerms, Set<String> andTerms,
- Set<String> orTerms, Set<Object> literals,
- Multimap<String, QueryTerm> terms, ASTJexlScript rootNode,
- TreeNode tree) {
- super();
- this.negatedTerms = negatedTerms;
- this.andTerms = andTerms;
- this.orTerms = orTerms;
- this.literals = literals;
- this.terms = terms;
- this.rootNode = rootNode;
- this.tree = tree;
- }
- public Set<String> getNegatedTerms() {
- return negatedTerms;
- }
- public Set<String> getAndTerms() {
- return andTerms;
- }
- public Set<String> getOrTerms() {
- return orTerms;
- }
- public Set<Object> getLiterals() {
- return literals;
- }
- public Multimap<String, QueryTerm> getTerms() {
- return terms;
- }
- public ASTJexlScript getRootNode() {
- return rootNode;
- }
- public TreeNode getTree() {
- return tree;
- }
- }
-
- private static final int SEED = 650567;
-
- private static LRUMap cache = new LRUMap();
-
- protected Set<String> negatedTerms = new HashSet<String>();
-
- private Set<String> andTerms = new HashSet<String>();
-
- private Set<String> orTerms = new HashSet<String>();
-
- /**
- * List of String, Integer, Float, etc literals that were passed in the query
- */
- private Set<Object> literals = new HashSet<Object>();
-
- /**
- * Map of terms (field names) to QueryTerm objects.
- */
- private Multimap<String,QueryTerm> terms = HashMultimap.create();
-
- private ASTJexlScript rootNode = null;
-
- private TreeNode tree = null;
-
- private int hashVal = 0;
-
- public QueryParser() {
- }
-
- private void reset() {
- this.negatedTerms.clear();
- this.andTerms.clear();
- this.orTerms.clear();
- this.literals.clear();
- this.terms = HashMultimap.create();
- }
-
- public void execute(String query) throws ParseException {
- reset();
- query = query.replaceAll("\\s+AND\\s+", " and ");
- query = query.replaceAll("\\s+OR\\s+", " or ");
- query = query.replaceAll("\\s+NOT\\s+", " not ");
-
- //Check to see if its in the cache
- Hash hash = MurmurHash.getInstance();
- this.hashVal = hash.hash(query.getBytes(), SEED);
- if (cache.containsKey(hashVal)) {
- CacheEntry entry = (CacheEntry) cache.get(hashVal);
- this.negatedTerms = entry.getNegatedTerms();
- this.andTerms = entry.getAndTerms();
- this.orTerms = entry.getOrTerms();
- this.literals = entry.getLiterals();
- this.terms = entry.getTerms();
- this.rootNode = entry.getRootNode();
- this.tree = entry.getTree();
- } else {
- Parser p = new Parser(new StringReader(";"));
- rootNode = p.parse(new StringReader(query), null);
- rootNode.childrenAccept(this, null);
- TreeBuilder builder = new TreeBuilder(rootNode);
- tree = builder.getRootNode();
- CacheEntry entry = new CacheEntry(this.negatedTerms, this.andTerms, this.orTerms, this.literals, this.terms, rootNode, tree);
- cache.put(hashVal, entry);
- }
-
- }
-
- public static void clearCache() {
- cache.clear();
- }
-
- /**
- *
- * @return this queries hash value
- */
- public int getHashValue() {
- return this.hashVal;
- }
-
- public TreeNode getIteratorTree() {
- return this.tree;
- }
-
- /**
- *
- * @return JEXL abstract syntax tree
- */
- public ASTJexlScript getAST() {
- return this.rootNode;
- }
-
- /**
- *
- * @return Set of field names to use in the optimizer for nots. As a general
- * rule none of these terms should be used to find an event and should they
- * should be evaluated on each event after being found.
- */
- public Set<String> getNegatedTermsForOptimizer() {
- return negatedTerms;
- }
-
- /**
- *
- * @return Set of field names to use in the optimizer for ands. As a general
- * rule any one term of an and clause can be used to find associated events.
- */
- public Set<String> getAndTermsForOptimizer() {
- return andTerms;
- }
-
-
- /**
- *
- * @return Set of field names to use in the optimizer for ors. As a general rule
- * any terms that are part of an or clause need to be searched to find the
- * associated events.
- */
- public Set<String> getOrTermsForOptimizer() {
- return orTerms;
- }
-
- /**
- *
- * @return String, Integer, and Float literals used in the query.
- */
- public Set<Object> getQueryLiterals() {
- return literals;
- }
-
- /**
- *
- * @return Set of all identifiers (field names) in the query.
- */
- public Set<String> getQueryIdentifiers() {
- return terms.keySet();
- }
-
- /**
- *
- * @return map of term (field name) to QueryTerm object
- */
- public Multimap<String,QueryTerm> getQueryTerms() {
- return terms;
- }
-
- public Object visit(SimpleNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTJexlScript node, Object data) {
- return null;
- }
-
- public Object visit(ASTBlock node, Object data) {
- return null;
- }
-
- public Object visit(ASTAmbiguous node, Object data) {
- return null;
- }
-
- public Object visit(ASTIfStatement node, Object data) {
- return null;
- }
-
- public Object visit(ASTWhileStatement node, Object data) {
- return null;
- }
-
- public Object visit(ASTForeachStatement node, Object data) {
- return null;
- }
-
- public Object visit(ASTAssignment node, Object data) {
- return null;
- }
-
- public Object visit(ASTTernaryNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTOrNode node, Object data) {
- boolean previouslyInOrContext = false;
- EvaluationContext ctx = null;
- if (null != data && data instanceof EvaluationContext) {
- ctx = (EvaluationContext) data;
- previouslyInOrContext = ctx.inOrContext;
- } else {
- ctx = new EvaluationContext();
- }
- ctx.inOrContext = true;
- //Process both sides of this node.
- node.jjtGetChild(0).jjtAccept(this, ctx);
- node.jjtGetChild(1).jjtAccept(this, ctx);
- //reset the state
- if (null != data && !previouslyInOrContext)
- ctx.inOrContext = false;
- return null;
- }
-
- public Object visit(ASTAndNode node, Object data) {
- boolean previouslyInAndContext = false;
- EvaluationContext ctx = null;
- if (null != data && data instanceof EvaluationContext) {
- ctx = (EvaluationContext) data;
- previouslyInAndContext = ctx.inAndContext;
- } else {
- ctx = new EvaluationContext();
- }
- ctx.inAndContext = true;
- //Process both sides of this node.
- node.jjtGetChild(0).jjtAccept(this, ctx);
- node.jjtGetChild(1).jjtAccept(this, ctx);
- //reset the state
- if (null != data && !previouslyInAndContext)
- ctx.inAndContext = false;
- return null;
- }
-
- public Object visit(ASTBitwiseOrNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTBitwiseXorNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTBitwiseAndNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTEQNode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = false;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTNENode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = true;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- if (negated)
- negatedTerms.add(fieldName.toString());
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTLTNode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = false;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTGTNode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = false;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTLENode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = false;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTGENode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = false;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTERNode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = false;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTNRNode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = true;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- if (negated)
- negatedTerms.add(fieldName.toString());
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- terms.put(fieldName.toString(), term);
- return null;
- }
-
- public Object visit(ASTAdditiveNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTAdditiveOperator node, Object data) {
- return null;
- }
-
- public Object visit(ASTMulNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTDivNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTModNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTUnaryMinusNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTBitwiseComplNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTNotNode node, Object data) {
- boolean previouslyInNotContext = false;
- EvaluationContext ctx = null;
- if (null != data && data instanceof EvaluationContext) {
- ctx = (EvaluationContext) data;
- previouslyInNotContext = ctx.inNotContext;
- } else {
- ctx = new EvaluationContext();
- }
- ctx.inNotContext = true;
- //Process both sides of this node.
- node.jjtGetChild(0).jjtAccept(this, ctx);
- //reset the state
- if (null != data && !previouslyInNotContext)
- ctx.inNotContext = false;
- return null;
- }
-
- public Object visit(ASTIdentifier node, Object data) {
- if (data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inAndContext)
- andTerms.add(node.image);
- if (ctx.inNotContext)
- negatedTerms.add(node.image);
- if (ctx.inOrContext)
- orTerms.add(node.image);
- }
- return new TermResult(node.image);
- }
-
- public Object visit(ASTNullLiteral node, Object data) {
- literals.add(node.image);
- return new LiteralResult(node.image);
- }
-
- public Object visit(ASTTrueNode node, Object data) {
- return new LiteralResult(node.image);
- }
-
- public Object visit(ASTFalseNode node, Object data) {
- return new LiteralResult(node.image);
- }
-
- public Object visit(ASTIntegerLiteral node, Object data) {
- literals.add(node.image);
- return new LiteralResult(node.image);
- }
-
- public Object visit(ASTFloatLiteral node, Object data) {
- literals.add(node.image);
- return new LiteralResult(node.image);
- }
-
- public Object visit(ASTStringLiteral node, Object data) {
- literals.add("'"+node.image+"'");
- return new LiteralResult("'"+node.image+"'");
- }
-
- public Object visit(ASTArrayLiteral node, Object data) {
- return null;
- }
-
- public Object visit(ASTMapLiteral node, Object data) {
- return null;
- }
-
- public Object visit(ASTMapEntry node, Object data) {
- return null;
- }
-
- public Object visit(ASTEmptyFunction node, Object data) {
- return null;
- }
-
- public Object visit(ASTSizeFunction node, Object data) {
- return null;
- }
-
- public Object visit(ASTFunctionNode node, Object data) {
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = true;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- //used to rebuild function call from the AST
- StringBuilder buf = new StringBuilder();
- String sep = "";
- // objectNode 0 is the prefix
- buf.append(node.jjtGetChild(0).image).append(":");
- // objectNode 1 is the identifier , the others are parameters.
- buf.append(node.jjtGetChild(1).image).append("(");
- // process the remaining arguments
- FunctionResult fr = new FunctionResult();
- int argc = node.jjtGetNumChildren() - 2;
- for (int i = 0; i < argc; i++) {
- //Process both sides of this node.
- Object result = node.jjtGetChild(i + 2).jjtAccept(this, data);
- if (result instanceof TermResult) {
- TermResult tr = (TermResult) result;
- fr.getTerms().add(tr);
- buf.append(sep).append(tr.value);
- sep = ", ";
- } else {
- buf.append(sep).append(node.jjtGetChild(i + 2).image);
- sep = ", ";
- }
- }
- buf.append(")");
- //Capture the entire function call for each function parameter
- for (TermResult tr : fr.terms)
- terms.put((String) tr.value, new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), buf.toString()));
- return fr;
- }
-
- public Object visit(ASTMethodNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTSizeMethod node, Object data) {
- return null;
- }
-
- public Object visit(ASTConstructorNode node, Object data) {
- return null;
- }
-
- public Object visit(ASTArrayAccess node, Object data) {
- return null;
- }
-
- public Object visit(ASTReference node, Object data) {
- return node.jjtGetChild(0).jjtAccept(this, data);
- }
-
- protected void decodeResults(Object left, Object right, StringBuilder fieldName, ObjectHolder holder) {
- if (left instanceof TermResult) {
- TermResult tr = (TermResult) left;
- fieldName.append((String) tr.value);
- //Then the right has to be the value
- if (right instanceof LiteralResult) {
- holder.setObject(((LiteralResult) right).value);
- } else {
- throw new IllegalArgumentException("Object mismatch");
- }
- } else if (right instanceof TermResult) {
- TermResult tr = (TermResult) right;
- fieldName.append((String) tr.value);
- if (left instanceof LiteralResult) {
- holder.setObject(((LiteralResult) left).value);
- } else {
- throw new IllegalArgumentException("Object mismatch");
- }
-
- } else {
- throw new IllegalArgumentException("No Term specified in query");
- }
- }
+
+ public static class QueryTerm {
+ private boolean negated = false;
+ private String operator = null;
+ private Object value = null;
+
+ public QueryTerm(boolean negated, String operator, Object value) {
+ super();
+ this.negated = negated;
+ this.operator = operator;
+ this.value = value;
+ }
+
+ public boolean isNegated() {
+ return negated;
+ }
+
+ public String getOperator() {
+ return operator;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setNegated(boolean negated) {
+ this.negated = negated;
+ }
+
+ public void setOperator(String operator) {
+ this.operator = operator;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("negated: ").append(negated).append(", operator: ").append(operator).append(", value: ").append(value);
+ return buf.toString();
+ }
+ }
+
+ /**
+ * Holder object
+ */
+ static class ObjectHolder {
+ Object object;
+
+ public Object getObject() {
+ return object;
+ }
+
+ public void setObject(Object object) {
+ this.object = object;
+ }
+ }
+
+ static class FunctionResult {
+ private List<TermResult> terms = new ArrayList<TermResult>();
+
+ public List<TermResult> getTerms() {
+ return terms;
+ }
+ }
+
+ /**
+ * Holder object for a term (i.e. field name)
+ */
+ static class TermResult {
+ Object value;
+
+ public TermResult(Object value) {
+ this.value = value;
+ }
+ }
+
+ /**
+ * Holder object for a literal (integer, float, string, or null literal) value
+ */
+ static class LiteralResult {
+ Object value;
+
+ public LiteralResult(Object value) {
+ this.value = value;
+ }
+ }
+
+ /**
+ * Object used to store context information as the AST is being iterated over.
+ */
+ static class EvaluationContext {
+ boolean inOrContext = false;
+ boolean inNotContext = false;
+ boolean inAndContext = false;
+ }
+
+ /**
+ * Object to store information from previously parsed queries.
+ */
+ private static class CacheEntry {
+ private Set<String> negatedTerms = null;
+ private Set<String> andTerms = null;
+ private Set<String> orTerms = null;
+ private Set<Object> literals = null;
+ private Multimap<String,QueryTerm> terms = null;
+ private ASTJexlScript rootNode = null;
+ private TreeNode tree = null;
+
+ public CacheEntry(Set<String> negatedTerms, Set<String> andTerms, Set<String> orTerms, Set<Object> literals, Multimap<String,QueryTerm> terms,
+ ASTJexlScript rootNode, TreeNode tree) {
+ super();
+ this.negatedTerms = negatedTerms;
+ this.andTerms = andTerms;
+ this.orTerms = orTerms;
+ this.literals = literals;
+ this.terms = terms;
+ this.rootNode = rootNode;
+ this.tree = tree;
+ }
+
+ public Set<String> getNegatedTerms() {
+ return negatedTerms;
+ }
+
+ public Set<String> getAndTerms() {
+ return andTerms;
+ }
+
+ public Set<String> getOrTerms() {
+ return orTerms;
+ }
+
+ public Set<Object> getLiterals() {
+ return literals;
+ }
+
+ public Multimap<String,QueryTerm> getTerms() {
+ return terms;
+ }
+
+ public ASTJexlScript getRootNode() {
+ return rootNode;
+ }
+
+ public TreeNode getTree() {
+ return tree;
+ }
+ }
+
+ private static final int SEED = 650567;
+
+ private static LRUMap cache = new LRUMap();
+
+ protected Set<String> negatedTerms = new HashSet<String>();
+
+ private Set<String> andTerms = new HashSet<String>();
+
+ private Set<String> orTerms = new HashSet<String>();
+
+ /**
+ * List of String, Integer, Float, etc literals that were passed in the query
+ */
+ private Set<Object> literals = new HashSet<Object>();
+
+ /**
+ * Map of terms (field names) to QueryTerm objects.
+ */
+ private Multimap<String,QueryTerm> terms = HashMultimap.create();
+
+ private ASTJexlScript rootNode = null;
+
+ private TreeNode tree = null;
+
+ private int hashVal = 0;
+
+ public QueryParser() {}
+
+ private void reset() {
+ this.negatedTerms.clear();
+ this.andTerms.clear();
+ this.orTerms.clear();
+ this.literals.clear();
+ this.terms = HashMultimap.create();
+ }
+
+ public void execute(String query) throws ParseException {
+ reset();
+ query = query.replaceAll("\\s+AND\\s+", " and ");
+ query = query.replaceAll("\\s+OR\\s+", " or ");
+ query = query.replaceAll("\\s+NOT\\s+", " not ");
+
+ // Check to see if its in the cache
+ Hash hash = MurmurHash.getInstance();
+ this.hashVal = hash.hash(query.getBytes(), SEED);
+ CacheEntry entry = null;
+ synchronized (cache) {
+ entry = (CacheEntry) cache.get(hashVal);
+ }
+ if (entry != null) {
+ this.negatedTerms = entry.getNegatedTerms();
+ this.andTerms = entry.getAndTerms();
+ this.orTerms = entry.getOrTerms();
+ this.literals = entry.getLiterals();
+ this.terms = entry.getTerms();
+ this.rootNode = entry.getRootNode();
+ this.tree = entry.getTree();
+ } else {
+ Parser p = new Parser(new StringReader(";"));
+ rootNode = p.parse(new StringReader(query), null);
+ rootNode.childrenAccept(this, null);
+ TreeBuilder builder = new TreeBuilder(rootNode);
+ tree = builder.getRootNode();
+ entry = new CacheEntry(this.negatedTerms, this.andTerms, this.orTerms, this.literals, this.terms, rootNode, tree);
+ synchronized (cache) {
+ cache.put(hashVal, entry);
+ }
+ }
+
+ }
+
+ /**
+ *
+ * @return this queries hash value
+ */
+ public int getHashValue() {
+ return this.hashVal;
+ }
+
+ public TreeNode getIteratorTree() {
+ return this.tree;
+ }
+
+ /**
+ *
+ * @return JEXL abstract syntax tree
+ */
+ public ASTJexlScript getAST() {
+ return this.rootNode;
+ }
+
+ /**
+ *
+ * @return Set of field names to use in the optimizer for nots. As a general rule none of these terms should be used to find an event and should they should
+ * be evaluated on each event after being found.
+ */
+ public Set<String> getNegatedTermsForOptimizer() {
+ return negatedTerms;
+ }
+
+ /**
+ *
+ * @return Set of field names to use in the optimizer for ands. As a general rule any one term of an and clause can be used to find associated events.
+ */
+ public Set<String> getAndTermsForOptimizer() {
+ return andTerms;
+ }
+
+ /**
+ *
+ * @return Set of field names to use in the optimizer for ors. As a general rule any terms that are part of an or clause need to be searched to find the
+ * associated events.
+ */
+ public Set<String> getOrTermsForOptimizer() {
+ return orTerms;
+ }
+
+ /**
+ *
+ * @return String, Integer, and Float literals used in the query.
+ */
+ public Set<Object> getQueryLiterals() {
+ return literals;
+ }
+
+ /**
+ *
+ * @return Set of all identifiers (field names) in the query.
+ */
+ public Set<String> getQueryIdentifiers() {
+ return terms.keySet();
+ }
+
+ /**
+ *
+ * @return map of term (field name) to QueryTerm object
+ */
+ public Multimap<String,QueryTerm> getQueryTerms() {
+ return terms;
+ }
+
+ public Object visit(SimpleNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTJexlScript node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTBlock node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTAmbiguous node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTIfStatement node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTWhileStatement node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTForeachStatement node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTAssignment node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTTernaryNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTOrNode node, Object data) {
+ boolean previouslyInOrContext = false;
+ EvaluationContext ctx = null;
+ if (null != data && data instanceof EvaluationContext) {
+ ctx = (EvaluationContext) data;
+ previouslyInOrContext = ctx.inOrContext;
+ } else {
+ ctx = new EvaluationContext();
+ }
+ ctx.inOrContext = true;
+ // Process both sides of this node.
+ node.jjtGetChild(0).jjtAccept(this, ctx);
+ node.jjtGetChild(1).jjtAccept(this, ctx);
+ // reset the state
+ if (null != data && !previouslyInOrContext)
+ ctx.inOrContext = false;
+ return null;
+ }
+
+ public Object visit(ASTAndNode node, Object data) {
+ boolean previouslyInAndContext = false;
+ EvaluationContext ctx = null;
+ if (null != data && data instanceof EvaluationContext) {
+ ctx = (EvaluationContext) data;
+ previouslyInAndContext = ctx.inAndContext;
+ } else {
+ ctx = new EvaluationContext();
+ }
+ ctx.inAndContext = true;
+ // Process both sides of this node.
+ node.jjtGetChild(0).jjtAccept(this, ctx);
+ node.jjtGetChild(1).jjtAccept(this, ctx);
+ // reset the state
+ if (null != data && !previouslyInAndContext)
+ ctx.inAndContext = false;
+ return null;
+ }
+
+ public Object visit(ASTBitwiseOrNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTBitwiseXorNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTBitwiseAndNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTEQNode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = false;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTNENode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = true;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ if (negated)
+ negatedTerms.add(fieldName.toString());
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTLTNode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = false;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTGTNode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = false;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTLENode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = false;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTGENode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = false;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTERNode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = false;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTNRNode node, Object data) {
+ StringBuilder fieldName = new StringBuilder();
+ ObjectHolder value = new ObjectHolder();
+ // Process both sides of this node.
+ Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ // Ignore functions in the query
+ if (left instanceof FunctionResult || right instanceof FunctionResult)
+ return null;
+ decodeResults(left, right, fieldName, value);
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = true;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ if (negated)
+ negatedTerms.add(fieldName.toString());
+ QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+ terms.put(fieldName.toString(), term);
+ return null;
+ }
+
+ public Object visit(ASTAdditiveNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTAdditiveOperator node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTMulNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTDivNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTModNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTUnaryMinusNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTBitwiseComplNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTNotNode node, Object data) {
+ boolean previouslyInNotContext = false;
+ EvaluationContext ctx = null;
+ if (null != data && data instanceof EvaluationContext) {
+ ctx = (EvaluationContext) data;
+ previouslyInNotContext = ctx.inNotContext;
+ } else {
+ ctx = new EvaluationContext();
+ }
+ ctx.inNotContext = true;
+ // Process both sides of this node.
+ node.jjtGetChild(0).jjtAccept(this, ctx);
+ // reset the state
+ if (null != data && !previouslyInNotContext)
+ ctx.inNotContext = false;
+ return null;
+ }
+
+ public Object visit(ASTIdentifier node, Object data) {
+ if (data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inAndContext)
+ andTerms.add(node.image);
+ if (ctx.inNotContext)
+ negatedTerms.add(node.image);
+ if (ctx.inOrContext)
+ orTerms.add(node.image);
+ }
+ return new TermResult(node.image);
+ }
+
+ public Object visit(ASTNullLiteral node, Object data) {
+ literals.add(node.image);
+ return new LiteralResult(node.image);
+ }
+
+ public Object visit(ASTTrueNode node, Object data) {
+ return new LiteralResult(node.image);
+ }
+
+ public Object visit(ASTFalseNode node, Object data) {
+ return new LiteralResult(node.image);
+ }
+
+ public Object visit(ASTIntegerLiteral node, Object data) {
+ literals.add(node.image);
+ return new LiteralResult(node.image);
+ }
+
+ public Object visit(ASTFloatLiteral node, Object data) {
+ literals.add(node.image);
+ return new LiteralResult(node.image);
+ }
+
+ public Object visit(ASTStringLiteral node, Object data) {
+ literals.add("'" + node.image + "'");
+ return new LiteralResult("'" + node.image + "'");
+ }
+
+ public Object visit(ASTArrayLiteral node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTMapLiteral node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTMapEntry node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTEmptyFunction node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTSizeFunction node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTFunctionNode node, Object data) {
+ // We need to check to see if we are in a NOT context. If so,
+ // then we need to reverse the negation.
+ boolean negated = true;
+ if (null != data && data instanceof EvaluationContext) {
+ EvaluationContext ctx = (EvaluationContext) data;
+ if (ctx.inNotContext)
+ negated = !negated;
+ }
+ // used to rebuild function call from the AST
+ StringBuilder buf = new StringBuilder();
+ String sep = "";
+ // objectNode 0 is the prefix
+ buf.append(node.jjtGetChild(0).image).append(":");
+ // objectNode 1 is the identifier , the others are parameters.
+ buf.append(node.jjtGetChild(1).image).append("(");
+ // process the remaining arguments
+ FunctionResult fr = new FunctionResult();
+ int argc = node.jjtGetNumChildren() - 2;
+ for (int i = 0; i < argc; i++) {
+ // Process both sides of this node.
+ Object result = node.jjtGetChild(i + 2).jjtAccept(this, data);
+ if (result instanceof TermResult) {
+ TermResult tr = (TermResult) result;
+ fr.getTerms().add(tr);
+ buf.append(sep).append(tr.value);
+ sep = ", ";
+ } else {
+ buf.append(sep).append(node.jjtGetChild(i + 2).image);
+ sep = ", ";
+ }
+ }
+ buf.append(")");
+ // Capture the entire function call for each function parameter
+ for (TermResult tr : fr.terms)
+ terms.put((String) tr.value, new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), buf.toString()));
+ return fr;
+ }
+
+ public Object visit(ASTMethodNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTSizeMethod node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTConstructorNode node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTArrayAccess node, Object data) {
+ return null;
+ }
+
+ public Object visit(ASTReference node, Object data) {
+ return node.jjtGetChild(0).jjtAccept(this, data);
+ }
+
+ protected void decodeResults(Object left, Object right, StringBuilder fieldName, ObjectHolder holder) {
+ if (left instanceof TermResult) {
+ TermResult tr = (TermResult) left;
+ fieldName.append((String) tr.value);
+ // Then the right has to be the value
+ if (right instanceof LiteralResult) {
+ holder.setObject(((LiteralResult) right).value);
+ } else {
+ throw new IllegalArgumentException("Object mismatch");
+ }
+ } else if (right instanceof TermResult) {
+ TermResult tr = (TermResult) right;
+ fieldName.append((String) tr.value);
+ if (left instanceof LiteralResult) {
+ holder.setObject(((LiteralResult) left).value);
+ } else {
+ throw new IllegalArgumentException("Object mismatch");
+ }
+
+ } else {
+ throw new IllegalArgumentException("No Term specified in query");
+ }
+ }
}
Modified: incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java?rev=1224966&r1=1224965&r2=1224966&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java (original)
+++ incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java Tue Dec 27 18:19:43 2011
@@ -28,6 +28,13 @@ import java.util.TreeSet;
import logic.AbstractQueryLogic;
import normalizer.Normalizer;
+import org.apache.accumulo.core.client.BatchScanner;
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.security.Authorizations;
import org.apache.commons.jexl2.parser.ASTAndNode;
import org.apache.commons.jexl2.parser.ASTEQNode;
import org.apache.commons.jexl2.parser.ASTERNode;
@@ -50,13 +57,6 @@ import org.apache.log4j.Logger;
import protobuf.Uid;
import util.TextUtil;
-import org.apache.accumulo.core.client.BatchScanner;
-import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.TableNotFoundException;
-import org.apache.accumulo.core.data.Key;
-import org.apache.accumulo.core.data.Range;
-import org.apache.accumulo.core.data.Value;
-import org.apache.accumulo.core.security.Authorizations;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
@@ -758,66 +758,171 @@ public class RangeCalculator extends Que
rightCardinality = 0L;
TermRange rightRange = ctx.lastRange;
if (log.isDebugEnabled())
- log.debug("[AND-right] term: " + ctx.lastProcessedTerm + ", cardinality: " + rightCardinality + ", ranges: " + rightRange.getRanges().size());
-
- //reset the state
- if (null != data && !previouslyInAndContext)
- ctx.inAndContext = false;
-
- long card = 0L;
- TermRange andRange = new TermRange("AND_RESULT", "foo");
- if ((leftCardinality > 0 && leftCardinality <= rightCardinality) || rightCardinality == 0) {
- card = leftCardinality;
- andRange.addAll(leftRange.getRanges());
- } else if ((rightCardinality > 0 && rightCardinality <= leftCardinality) || leftCardinality == 0) {
- card = rightCardinality;
- andRange.addAll(rightRange.getRanges());
- }
- if (log.isDebugEnabled())
- log.debug("[AND] results: " + andRange.getRanges().toString());
- ctx.lastRange = andRange;
- ctx.lastProcessedTerm = "AND_RESULT";
- this.termCardinalities.put("AND_RESULT", card);
-
- return null;
- }
-
- @Override
- public Object visit(ASTEQNode node, Object data) {
- StringBuilder fieldName = new StringBuilder();
- ObjectHolder value = new ObjectHolder();
- //Process both sides of this node.
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- //Ignore functions in the query
- if (left instanceof FunctionResult || right instanceof FunctionResult)
- return null;
- decodeResults(left, right, fieldName, value);
- //We need to check to see if we are in a NOT context. If so,
- //then we need to reverse the negation.
- boolean negated = false;
- if (null != data && data instanceof EvaluationContext) {
- EvaluationContext ctx = (EvaluationContext) data;
- if (ctx.inNotContext)
- negated = !negated;
- }
- QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
- termsCopy.put(fieldName.toString(), term);
- //Get the terms from the global index
- //Remove the begin and end ' marks
- String termValue = null;
- if (((String) term.getValue()).startsWith("'") && ((String) term.getValue()).endsWith("'"))
- termValue = ((String) term.getValue()).substring(1, ((String) term.getValue()).length() - 1);
+ log.debug("Ranges for Global Index query: " + m.toString());
+ this.globalIndexResults.putAll(queryGlobalIndex(m, equals.getKey().getFieldName(), this.indexTableName, false, equals.getKey(), typeFilter));
+ }
+ } catch (TableNotFoundException e) {
+ log.error("index table not found", e);
+ throw new RuntimeException(" index table not found", e);
+ }
+
+ if (log.isDebugEnabled())
+ log.debug("Ranges from Global Index query: " + globalIndexResults.toString());
+
+ // Now traverse the AST
+ EvaluationContext ctx = new EvaluationContext();
+ this.getAST().childrenAccept(this, ctx);
+
+ if (ctx.lastRange.getRanges().size() == 0) {
+ log.debug("No resulting range set");
+ } else {
+ if (log.isDebugEnabled())
+ log.debug("Setting range results to: " + ctx.lastRange.getRanges().toString());
+ this.result = ctx.lastRange.getRanges();
+ }
+ }
+
+ /**
+ *
+ * @return set of ranges to use for the shard table
+ */
+ public Set<Range> getResult() {
+ return result;
+ }
+
+ /**
+ *
+ * @return map of field names to index field values
+ */
+ public Multimap<String,String> getIndexEntries() {
+ return indexEntries;
+ }
+
+ public Map<String,String> getIndexValues() {
+ return indexValues;
+ }
+
+ /**
+ *
+ * @return Cardinality for each field name.
+ */
+ public Map<String,Long> getTermCardinalities() {
+ return termCardinalities;
+ }
+
+ /**
+ *
+ * @param indexRanges
+ * @param tableName
+ * @param isReverse
+ * switch that determines whether or not to reverse the results
+ * @param override
+ * mapKey for wildcard and range queries that specify which mapkey to use in the results
+ * @param typeFilter
+ * - optional list of datatypes
+ * @return
+ * @throws TableNotFoundException
+ */
+ protected Map<MapKey,TermRange> queryGlobalIndex(Map<MapKey,Set<Range>> indexRanges, String specificFieldName, String tableName, boolean isReverse,
+ MapKey override, Set<String> typeFilter) throws TableNotFoundException {
+
+ // The results map where the key is the field name and field value and the
+ // value is a set of ranges. The mapkey will always be the field name
+ // and field value that was passed in the original query. The TermRange
+ // will contain the field name and field value found in the index.
+ Map<MapKey,TermRange> results = new HashMap<MapKey,TermRange>();
+
+ // Seed the results map and create the range set for the batch scanner
+ Set<Range> rangeSuperSet = new HashSet<Range>();
+ for (Entry<MapKey,Set<Range>> entry : indexRanges.entrySet()) {
+ rangeSuperSet.addAll(entry.getValue());
+ TermRange tr = new TermRange(entry.getKey().getFieldName(), entry.getKey().getFieldValue());
+ if (null == override)
+ results.put(entry.getKey(), tr);
+ else
+ results.put(override, tr);
+ }
+
+ if (log.isDebugEnabled())
+ log.debug("Querying global index table: " + tableName + ", range: " + rangeSuperSet.toString() + " colf: " + specificFieldName);
+ BatchScanner bs = this.c.createBatchScanner(tableName, this.auths, this.queryThreads);
+ bs.setRanges(rangeSuperSet);
+ if (null != specificFieldName) {
+ bs.fetchColumnFamily(new Text(specificFieldName));
+ }
+
+ for (Entry<Key,Value> entry : bs) {
+ if (log.isDebugEnabled()) {
+ log.debug("Index entry: " + entry.getKey().toString());
+ }
+ String fieldValue = null;
+ if (!isReverse) {
+ fieldValue = entry.getKey().getRow().toString();
+ } else {
+ StringBuilder buf = new StringBuilder(entry.getKey().getRow().toString());
+ fieldValue = buf.reverse().toString();
+ }
+
+ String fieldName = entry.getKey().getColumnFamily().toString();
+ // Get the shard id and datatype from the colq
+ String colq = entry.getKey().getColumnQualifier().toString();
+ int separator = colq.indexOf(EvaluatingIterator.NULL_BYTE_STRING);
+ String shardId = null;
+ String datatype = null;
+ if (separator != -1) {
+ shardId = colq.substring(0, separator);
+ datatype = colq.substring(separator + 1);
+ } else {
+ shardId = colq;
+ }
+ // Skip this entry if the type is not correct
+ if (null != datatype && null != typeFilter && !typeFilter.contains(datatype))
+ continue;
+ // Parse the UID.List object from the value
+ Uid.List uidList = null;
+ try {
+ uidList = Uid.List.parseFrom(entry.getValue().get());
+ } catch (InvalidProtocolBufferException e) {
+ // Don't add UID information, at least we know what shards
+ // it is located in.
+ }
+
+ // Add the count for this shard to the total count for the term.
+ long count = 0;
+ Long storedCount = termCardinalities.get(fieldName);
+ if (null == storedCount || 0 == storedCount) {
+ count = uidList.getCOUNT();
+ } else {
+ count = uidList.getCOUNT() + storedCount;
+ }
+ termCardinalities.put(fieldName, count);
+ this.indexEntries.put(fieldName, fieldValue);
+
+ if (null == override)
+ this.indexValues.put(fieldValue, fieldValue);
+ else
+ this.indexValues.put(fieldValue, override.getOriginalQueryValue());
+
+ // Create the keys
+ Text shard = new Text(shardId);
+ if (uidList.getIGNORE()) {
+ // Then we create a scan range that is the entire shard
+ if (null == override)
+ results.get(new MapKey(fieldName, fieldValue)).add(new Range(shard));
else
- termValue = (String) term.getValue();
- //Get the values found in the index for this query term
- TermRange ranges = null;
- for (MapKey key : this.originalQueryValues.get(termValue)) {
- if (key.getFieldName().equalsIgnoreCase(fieldName.toString())) {
- ranges = this.globalIndexResults.get(key);
- if (log.isDebugEnabled())
- log.debug("Results for cached index ranges for key: " + key + " are " + ranges);
- }
+ results.get(override).add(new Range(shard));
+ } else {
+ // We should have UUIDs, create event ranges
+ for (String uuid : uidList.getUIDList()) {
+ Text cf = new Text(datatype);
+ TextUtil.textAppend(cf, uuid);
+ Key startKey = new Key(shard, cf);
+ Key endKey = new Key(shard, new Text(cf.toString() + EvaluatingIterator.NULL_BYTE_STRING));
+ Range eventRange = new Range(startKey, true, endKey, false);
+ if (null == override)
+ results.get(new MapKey(fieldName, fieldValue)).add(eventRange);
+ else
+ results.get(override).add(eventRange);
}
//If no result for this field name and value, then add empty range
if (null == ranges)
Modified: incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java?rev=1224966&r1=1224965&r2=1224966&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java (original)
+++ incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java Tue Dec 27 18:19:43 2011
@@ -53,192 +53,195 @@ import org.apache.accumulo.core.client.Z
@Stateless
@Local(IQuery.class)
public class Query implements IQuery {
-
- private static final Logger log = Logger.getLogger(Query.class);
-
- //Inject values from XML configuration file
- @Resource(name="instanceName")
- private String instanceName;
-
- @Resource(name="zooKeepers")
- private String zooKeepers;
-
- @Resource(name="username")
- private String username;
-
- @Resource(name="password")
- private String password;
-
- @Resource(name="tableName")
- private String tableName;
-
- @Resource(name="partitions")
- private int partitions;
-
- @Resource(name="threads")
- private int threads;
-
- private static final String XSL = "http://localhost:8080/accumulo-sample/style.xsl";
-
- @PostConstruct
- public void init() {
- log.info("Post Construct");
- }
-
- @PreDestroy
- public void close() {
- log.info("Close called.");
- }
-
- /*
- * (non-Javadoc)
- * @see sample.query.IQuery#html(java.lang.String, java.lang.String)
- */
- public String html(String query, String auths) {
- log.info("HTML query: " + query);
- URL u;
- try {
- u = new URL(XSL);
- } catch (MalformedURLException e1) {
- throw new EJBException("Unable to load XSL stylesheet", e1);
- }
- InputStream xslContent;
- try {
- xslContent = u.openStream();
- } catch (IOException e1) {
- throw new EJBException("Unable to get xsl content", e1);
- }
-
- StringWriter xml = new StringWriter();
- StringWriter html = new StringWriter();
-
- Results results = query(query, auths);
- try {
- //Marshall the query results object
- JAXBContext ctx = JAXBContext.newInstance(Results.class);
- Marshaller m = ctx.createMarshaller();
- m.marshal(results, xml);
-
- //Perform XSL transform on the xml.
- StringReader reader = new StringReader(xml.toString());
- TransformerFactory tf = TransformerFactory.newInstance();
- //Create the transformer from the xsl
- Templates xsl = tf.newTemplates(new StreamSource(xslContent));
- Transformer t = xsl.newTransformer();
- t.transform(new StreamSource(reader), new StreamResult(html));
-
- } catch (Exception e) {
- throw new EJBException("Error processing query results", e);
- } finally {
- try {
- xslContent.close();
- } catch (IOException e) {
- throw new EJBException("Unable to close input stream", e);
- }
- }
- return html.toString();
- }
-
- /*
- * (non-Javadoc)
- * @see sample.query.IQuery#xml(java.lang.String, java.lang.String)
- */
- public Results xml(String query, String auths) {
- log.info("XML query: " + query);
- return query(query, auths);
- }
-
- /*
- * (non-Javadoc)
- * @see sample.query.IQuery#json(java.lang.String, java.lang.String)
- */
- public Results json(String query, String auths) {
- log.info("JSON query: " + query);
- return query(query, auths);
- }
-
- /*
- * (non-Javadoc)
- * @see sample.query.IQuery#yaml(java.lang.String, java.lang.String)
- */
- public Results yaml(String query, String auths) {
- log.info("YAML query: " + query);
- return query(query, auths);
- }
-
- /*
- * (non-Javadoc)
- * @see sample.query.IQuery#content(java.lang.String, java.lang.String)
- */
- public Results content(String query, String auths) {
- log.info("Content query: " + query);
- Connector connector = null;
- if (null == instanceName || null == zooKeepers || null == username || null == password)
- throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName +
- ", zookeepers = " + this.zooKeepers + ", username = " + this.username +
- ", password = " + this.password +"]. Check values in ejb-jar.xml");
- Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
- try {
- log.info("Connecting to [instanceName = " + this.instanceName +
- ", zookeepers = " + this.zooKeepers + ", username = " + this.username +
- ", password = " + this.password +"].");
- connector = instance.getConnector(this.username, this.password.getBytes());
- } catch (Exception e) {
- throw new EJBException("Error getting connector from instance", e);
- }
-
- //Create list of auths
- List<String> authorizations = new ArrayList<String>();
- for (String a : auths.split(","))
- authorizations.add(a);
-
- ContentLogic table = new ContentLogic();
- table.setTableName(tableName);
- return table.runQuery(connector, query, authorizations);
-
- }
-
- /**
- * calls the query logic with the parameters, returns results
- *
- * @param query
- * @param auths
- * @return
- * @throws ParseException
- */
- public Results query(String query, String auths) {
-
- Connector connector = null;
- if (null == instanceName || null == zooKeepers || null == username || null == password)
- throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName +
- ", zookeepers = " + this.zooKeepers + ", username = " + this.username +
- ", password = " + this.password +"]. Check values in ejb-jar.xml");
- Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
- try {
- log.info("Connecting to [instanceName = " + this.instanceName +
- ", zookeepers = " + this.zooKeepers + ", username = " + this.username +
- ", password = " + this.password +"].");
- connector = instance.getConnector(this.username, this.password.getBytes());
- } catch (Exception e) {
- throw new EJBException("Error getting connector from instance", e);
- }
-
-
- //Create list of auths
- List<String> authorizations = new ArrayList<String>();
- for (String a : auths.split(","))
- authorizations.add(a);
-
- QueryLogic table = new QueryLogic();
- table.setTableName(tableName);
- table.setMetadataTableName(tableName+"Metadata");
- table.setIndexTableName(tableName+"Index");
- table.setReverseIndexTableName(tableName+"ReverseIndex");
- table.setQueryThreads(threads);
- table.setUnevaluatedFields("TEXT");
- table.setNumPartitions(partitions);
- table.setUseReadAheadIterator(false);
- return table.runQuery(connector, authorizations, query, null, null, null);
- }
-
+
+ private static final Logger log = Logger.getLogger(Query.class);
+
+ // Inject values from XML configuration file
+ @Resource(name = "instanceName")
+ private String instanceName;
+
+ @Resource(name = "zooKeepers")
+ private String zooKeepers;
+
+ @Resource(name = "username")
+ private String username;
+
+ @Resource(name = "password")
+ private String password;
+
+ @Resource(name = "tableName")
+ private String tableName;
+
+ @Resource(name = "partitions")
+ private int partitions;
+
+ @Resource(name = "threads")
+ private int threads;
+
+ private static final String XSL = "/accumulo-sample/style.xsl";
+
+ @PostConstruct
+ public void init() {
+ log.info("Post Construct");
+ }
+
+ @PreDestroy
+ public void close() {
+ log.info("Close called.");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see sample.query.IQuery#html(java.lang.String, java.lang.String)
+ */
+ public String html(String query, String auths) {
+ log.info("HTML query: " + query);
+ URL u;
+ try {
+ u = new URL("http://" + System.getProperty("jboss.bind.address") + ":" + System.getProperty("jboss.web.http.port") + XSL);
+ } catch (MalformedURLException e1) {
+ throw new EJBException("Unable to load XSL stylesheet", e1);
+ }
+ InputStream xslContent;
+ try {
+ xslContent = u.openStream();
+ } catch (IOException e1) {
+ throw new EJBException("Unable to get xsl content", e1);
+ }
+
+ StringWriter xml = new StringWriter();
+ StringWriter html = new StringWriter();
+
+ Results results = query(query, auths);
+ try {
+ // Marshall the query results object
+ JAXBContext ctx = JAXBContext.newInstance(Results.class);
+ Marshaller m = ctx.createMarshaller();
+ m.marshal(results, xml);
+
+ // Perform XSL transform on the xml.
+ StringReader reader = new StringReader(xml.toString());
+ TransformerFactory tf = TransformerFactory.newInstance();
+ // Create the transformer from the xsl
+ Templates xsl = tf.newTemplates(new StreamSource(xslContent));
+ Transformer t = xsl.newTransformer();
+ t.transform(new StreamSource(reader), new StreamResult(html));
+
+ } catch (Exception e) {
+ throw new EJBException("Error processing query results", e);
+ } finally {
+ try {
+ xslContent.close();
+ } catch (IOException e) {
+ throw new EJBException("Unable to close input stream", e);
+ }
+ }
+ return html.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see sample.query.IQuery#xml(java.lang.String, java.lang.String)
+ */
+ public Results xml(String query, String auths) {
+ log.info("XML query: " + query);
+ return query(query, auths);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see sample.query.IQuery#json(java.lang.String, java.lang.String)
+ */
+ public Results json(String query, String auths) {
+ log.info("JSON query: " + query);
+ return query(query, auths);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see sample.query.IQuery#yaml(java.lang.String, java.lang.String)
+ */
+ public Results yaml(String query, String auths) {
+ log.info("YAML query: " + query);
+ return query(query, auths);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see sample.query.IQuery#content(java.lang.String, java.lang.String)
+ */
+ public Results content(String query, String auths) {
+ log.info("Content query: " + query);
+ Connector connector = null;
+ if (null == instanceName || null == zooKeepers || null == username || null == password)
+ throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = "
+ + this.username + ", password = " + this.password + "]. Check values in ejb-jar.xml");
+ Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
+ try {
+ log.info("Connecting to [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = " + this.username + ", password = "
+ + this.password + "].");
+ connector = instance.getConnector(this.username, this.password.getBytes());
+ } catch (Exception e) {
+ throw new EJBException("Error getting connector from instance", e);
+ }
+
+ // Create list of auths
+ List<String> authorizations = new ArrayList<String>();
+ if (auths == null || "".equals(auths)) {
+ authorizations.add("all");
+ } else {
+ for (String a : auths.split(","))
+ authorizations.add(a);
+ }
+ ContentLogic table = new ContentLogic();
+ table.setTableName(tableName);
+ return table.runQuery(connector, query, authorizations);
+
+ }
+
+ /**
+ * calls the query logic with the parameters, returns results
+ *
+ * @param query
+ * @param auths
+ * @return
+ * @throws ParseException
+ */
+ public Results query(String query, String auths) {
+
+ Connector connector = null;
+ if (null == instanceName || null == zooKeepers || null == username || null == password)
+ throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = "
+ + this.username + ", password = " + this.password + "]. Check values in ejb-jar.xml");
+ Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
+ try {
+ log.info("Connecting to [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = " + this.username + ", password = "
+ + this.password + "].");
+ connector = instance.getConnector(this.username, this.password.getBytes());
+ } catch (Exception e) {
+ throw new EJBException("Error getting connector from instance", e);
+ }
+
+ // Create list of auths
+ List<String> authorizations = new ArrayList<String>();
+ for (String a : auths.split(","))
+ authorizations.add(a);
+
+ QueryLogic table = new QueryLogic();
+ table.setTableName(tableName);
+ table.setMetadataTableName(tableName + "Metadata");
+ table.setIndexTableName(tableName + "Index");
+ table.setReverseIndexTableName(tableName + "ReverseIndex");
+ table.setQueryThreads(threads);
+ table.setUnevaluatedFields("TEXT");
+ table.setNumPartitions(partitions);
+ table.setUseReadAheadIterator(false);
+ return table.runQuery(connector, authorizations, query, null, null, null);
+ }
+
}