package org.wonderdb.parser.jtree; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.wonderdb.expression.AndExpression; import org.wonderdb.expression.BasicExpression; import org.wonderdb.expression.Operand; import org.wonderdb.expression.VariableOperand; import org.wonderdb.query.parse.CollectionAlias; import org.wonderdb.query.parse.StaticOperand; import org.wonderdb.query.parser.jtree.DBSelectQueryJTree.ResultSetColumn; import org.wonderdb.query.parser.jtree.DBSelectQueryJTree.VirtualResultSetColumn; import org.wonderdb.query.plan.DataContext; import org.wonderdb.schema.CollectionMetadata; import org.wonderdb.schema.FunctionManager; import org.wonderdb.schema.SchemaMetadata; import org.wonderdb.schema.WonderDBFunction; import org.wonderdb.types.ByteArrayType; import org.wonderdb.types.ColumnNameMeta; import org.wonderdb.types.DBType; import org.wonderdb.types.DoubleType; import org.wonderdb.types.FloatType; import org.wonderdb.types.IntType; import org.wonderdb.types.LongType; import org.wonderdb.types.StringType; import org.wonderdb.types.UndefinedType; public class QueryEvaluator { DataContext context = null; // CollectionAlias ca = null; Map<String, CollectionAlias> aliasMap = new HashMap<String, CollectionAlias>(); public QueryEvaluator(Map<String, CollectionAlias> aliasMap, DataContext dataContext) { this.context = dataContext; this.aliasMap = aliasMap; // this.ca = ca; // this.fromMap = fromMap; } public void evaluate(SimpleNode node) { SimpleNode c = (SimpleNode) node.children[0]; switch (c.id) { case UQLParserTreeConstants.JJTSELECTSTMT: processSelectStmt(c); } } public void shouldQueryRewrite(SimpleNode start) { SimpleNode selectNode = (SimpleNode) start.children[0]; SimpleNode compareNode = null; SimpleNode node = null; for (int i = 0; i < selectNode.children.length; i++) { compareNode = (SimpleNode) selectNode.children[i]; if (compareNode.id == UQLParserTreeConstants.JJTFILTEREXPRESSION) { break; } } if (compareNode.id != UQLParserTreeConstants.JJTFILTEREXPRESSION) { return; } List<SimpleNode> list = new ArrayList<SimpleNode>(); List<SimpleNode> endList = new ArrayList<SimpleNode>(); node = compareNode; boolean foundOr = false; for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; if (n.id == UQLParserTreeConstants.JJTOR) { endList.add(n); foundOr = true; } else if (foundOr) { endList.add(n); foundOr = false; } else { list.add(n); } } node.children = new SimpleNode[list.size()+endList.size()]; for (int i = 0; i < list.size(); i++) { node.children[i] = list.get(i); } for (int i = 0; i < endList.size(); i++) { node.children[i+list.size()] = endList.get(i); } } public boolean processSelectStmt(SimpleNode startNode) { SimpleNode node = startNode; for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; switch (n.id) { case UQLParserTreeConstants.JJTFILTEREXPRESSION: processFilterExpression(n); Object val = n.jjtGetValue(); if (val instanceof Boolean) { return (Boolean) val; } else if (val instanceof UndefinedType) { return true; } else { throw new RuntimeException("Invalid syntax"); } default: break; } } return true; } private void processFilterExpression(SimpleNode node) { for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; switch (n.id) { case UQLParserTreeConstants.JJTCOMPAREEQUATION: processCompareEquation(n); break; default: break; } } node.jjtSetValue(((SimpleNode) node.children[0]).jjtGetValue()); } private void processCompareEquation(SimpleNode node) { for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; switch (n.id) { case UQLParserTreeConstants.JJTEQUALITYEQUATION: processEqualityEquation(n); break; default: break; } } evaluateCompareEquation(node); } private void evaluateCompareEquation(SimpleNode node) { boolean currentFlag = true; int op = -1; if (node.children.length == 1) { node.jjtSetValue( ((SimpleNode) node.children[0]).jjtGetValue()); return; } for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; boolean forBreak = false; switch (n.id) { case UQLParserTreeConstants.JJTEQUALITYEQUATION: currentFlag = evaluateAndOr(op, currentFlag, n.jjtGetValue()); if (op == UQLParserTreeConstants.JJTOR && currentFlag) { forBreak = true; break; } break; case UQLParserTreeConstants.JJTAND: case UQLParserTreeConstants.JJTOR: op = n.id; break; } if (forBreak) { break; } } node.jjtSetValue(currentFlag); } private boolean evaluateAndOr(int op, boolean currentFlag, Object val) { if (op < 0 && val != null) { if (val instanceof Boolean) { return (Boolean) val; } else { return true; } } else if (op < 0 && val == null) { throw new RuntimeException("Invalid expression"); } boolean b = false; if (val instanceof Boolean) { b = (Boolean) val; } switch (op) { case UQLParserTreeConstants.JJTAND: return val instanceof UndefinedType ? currentFlag : currentFlag && b; case UQLParserTreeConstants.JJTOR: return val instanceof UndefinedType ? currentFlag : currentFlag || b; } return false; } private void processEqualityEquation(SimpleNode node) { for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; switch(n.id) { case UQLParserTreeConstants.JJTMULTIPLICATIVEEXPRESSION: processMultiplicativeExpression(n); break; default: break; } } evaluateEqualityEquation(node); } @SuppressWarnings({ "rawtypes", "unchecked" }) private void evaluateEqualityEquation(SimpleNode node) { Comparable left = null; Comparable right = null; int op = -1; Object o1 = (( SimpleNode) node.children[0]).jjtGetValue(); Object o2 = null; if (node.children.length == 1) { node.jjtSetValue(o1); return; } if (node.children.length == 3) { op = ((SimpleNode) node.children[1]).id; o2 = (( SimpleNode) node.children[2]).jjtGetValue(); } if (o1 instanceof Comparable<?>) { left = (Comparable<?>) o1; } else { throw new RuntimeException("Invalid expression"); } if (o2 instanceof Comparable<?>) { right = (Comparable<?>) o2; } else { throw new RuntimeException("Invalid expression"); } if (left instanceof UndefinedType || right instanceof UndefinedType) { node.jjtSetValue(UndefinedType.getInstance()); return; } switch (op) { case UQLParserTreeConstants.JJTGT: node.jjtSetValue(left.compareTo(right) > 0); break; case UQLParserTreeConstants.JJTGE: node.jjtSetValue(left.compareTo(right) >= 0); break; case UQLParserTreeConstants.JJTLT: node.jjtSetValue(left.compareTo(right) < 0); break; case UQLParserTreeConstants.JJTLE: node.jjtSetValue(left.compareTo(right) <= 0); break; case UQLParserTreeConstants.JJTEQ: node.jjtSetValue(left.compareTo(right) == 0); break; case UQLParserTreeConstants.JJTNE: node.jjtSetValue(left.compareTo(right) != 0); break; } } public void processMultiplicativeExpression(SimpleNode node) { for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; switch(n.id) { case UQLParserTreeConstants.JJTUNARYEXPRESSION: processUnaryExpression(n); break; } } evaluateMultiplicativeExpression(node); } public void processUnaryExpression(SimpleNode node) { SimpleNode n = (SimpleNode) node.children[0]; switch(n.id) { case UQLParserTreeConstants.JJTFN: processFunction(n); break; case UQLParserTreeConstants.JJTSTR: processStr(n); break; case UQLParserTreeConstants.JJTCOLUMNANDALIAS: processColumnAlias(n); break; case UQLParserTreeConstants.JJTNUMBER: processNumber(n); break; case UQLParserTreeConstants.JJTQ: break; case UQLParserTreeConstants.JJTGROUPEDCOMPAREEQUATION: processGroupedquation(n); break; } node.jjtSetValue(n.jjtGetValue()); } private void processGroupedquation(SimpleNode node) { for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[0]; switch(n.id) { case UQLParserTreeConstants.JJTCOMPAREEQUATION: processCompareEquation(n); node.jjtSetValue(n.jjtGetValue()); break; } } } private void evaluateMultiplicativeExpression(SimpleNode node) { int op = -1; Object currentOperand = 0L; for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; switch(n.id) { case UQLParserTreeConstants.JJTPLUS: case UQLParserTreeConstants.JJTMINUS: case UQLParserTreeConstants.JJTMUL: case UQLParserTreeConstants.JJTDIV: op = n.id; continue; default: break; } currentOperand = process(op, currentOperand, n.jjtGetValue()); } node.jjtSetValue(currentOperand); } Object process(int op, Object op1, Object op2) { if (op1 instanceof UndefinedType || op2 instanceof UndefinedType) { return UndefinedType.getInstance(); } if (op >= 0 && op2 instanceof String) { throw new RuntimeException("Invalid expression"); } if (op1 instanceof Long && op2 instanceof Double) { op1 = new Double((Long) op1); } if (op1 instanceof Double && op2 instanceof Long) { op2 = new Double((Long) op2); } if (op1 instanceof Long && op2 instanceof Integer) { op2 = new Long(((Integer) op2).longValue()); } switch (op) { case UQLParserTreeConstants.JJTPLUS: if (op1 instanceof Double) { return (Double) op1 + (Double) op2; } else { return (Long) op1 + (Long) op2; } case UQLParserTreeConstants.JJTMINUS: if (op1 instanceof Double) { return (Double) op1 - (Double) op2; } else { return (Long) op1 - (Long) op2; } case UQLParserTreeConstants.JJTMUL: if (op1 instanceof Double) { return (Double) op1 * (Double) op2; } else { return (Long) op1 * (Long) op2; } case UQLParserTreeConstants.JJTDIV: if (op1 instanceof Double) { return (Double) op1 / (Double) op2; } else { return (Long) op1 / (Long) op2; } } return op2; } public static void processStr(SimpleNode node) { String s = node.jjtGetFirstToken().image; if (s == null || s.length() == 0) { return; } if (s.startsWith("\"") || s.startsWith("'")) { s = s.substring(1, s.length()-1); } node.jjtSetValue(s); } public void processColumnAlias(SimpleNode node) { String alias = ""; Token t1 = node.jjtGetFirstToken(); Token t2 = node.jjtGetLastToken(); if (t1 != t2) { alias = t1.image; } CollectionAlias ca = aliasMap.get(alias); DBType dt = context.getValue(ca, t2.image, null); if (dt != null) { if (dt instanceof StringType) { node.jjtSetValue(((StringType) dt).get()); } else if (dt instanceof IntType) { node.jjtSetValue(((IntType) dt).get()); } else if (dt instanceof LongType) { node.jjtSetValue(((LongType) dt).get()); } else if (dt instanceof FloatType) { node.jjtSetValue(((FloatType) dt).get()); } else if (dt instanceof DoubleType) { node.jjtSetValue(((DoubleType) dt).get()); } else if (dt instanceof ByteArrayType) { node.jjtSetValue(dt); } else if (dt instanceof UndefinedType) { node.jjtSetValue(dt); } else { throw new RuntimeException("Invalid type"); } } else { node.jjtSetValue(UndefinedType.getInstance()); } } public static void processCA(SimpleNode node) { Token t1 = node.jjtGetFirstToken(); Token t2 = node.jjtGetLastToken(); if (t1 != t2) { node.jjtSetValue(t1.image); } else { node.jjtSetValue(t1.image + "." + t2.image); } } public static void processNumber(SimpleNode node) { Node[] children = node.children; if (children == null || children.length == 0) { throw new RuntimeException("Invalid syntax:"); } boolean negative = false; String decimal = ""; String precision = ""; for (int i = 0; i < children.length; i++) { SimpleNode n = (SimpleNode) children[i]; if (n.id == UQLParserTreeConstants.JJTMINUS) { negative = true; } else if (n.id == UQLParserTreeConstants.JJTDECIMAL) { decimal = n.jjtGetFirstToken().image; } else if (n.id == UQLParserTreeConstants.JJTPRECISION) { precision = n.jjtGetFirstToken().image; } } if ("".equals(precision)) { String value = negative ? "-"+decimal : decimal; node.jjtSetValue(Long.parseLong(value)); } else { String value = negative ? "-"+decimal+"."+precision : decimal+"."+precision; node.jjtSetValue(Double.parseDouble(value)); } } private void processFunction(SimpleNode node) { for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; switch(n.id) { case UQLParserTreeConstants.JJTIDENTIFIER: processIdentifier(n); break; default: processMultiplicativeExpression(n); break; } } evaluateFunction(node); } public void evaluateFunction(SimpleNode node) { String functionName = (String) ((SimpleNode) node.children[0]).jjtGetValue(); WonderDBFunction function = FunctionManager.getInstance().getFunction(functionName, node); function.process(context); } private void processIdentifier(SimpleNode node) { node.jjtSetValue(node.jjtGetFirstToken().image); } public Map<CollectionAlias, List<Integer>> getColumns(SimpleNode node, Map<String, CollectionAlias> fromMap, List<ResultSetColumn> resultSetColumns) { Map<CollectionAlias, List<Integer>> map = new HashMap<CollectionAlias, List<Integer>>(); getColumns(node, fromMap, map, resultSetColumns, true); return map; } public void getColumns(SimpleNode node, Map<String, CollectionAlias> fromMap, Map<CollectionAlias, List<Integer>> map, List<ResultSetColumn> resultSetColumns, boolean isResultSet) { StringBuilder sb = new StringBuilder(); if (node.id == UQLParserTreeConstants.JJTTABLEDEF) { isResultSet = false; } if (node.id == UQLParserTreeConstants.JJTFN) { VirtualResultSetColumn rsc = new VirtualResultSetColumn(); SimpleNode fnNode = (SimpleNode) node.children[0]; rsc.node = fnNode; String fnName = (String) fnNode.jjtGetFirstToken().image; rsc.ca = new CollectionAlias("", ""); WonderDBFunction fn = FunctionManager.getInstance().getFunction(fnName, node); rsc.function = fn; if (isResultSet) { resultSetColumns.add(rsc); } } else if (node.id == UQLParserTreeConstants.JJTCOLUMNANDALIAS) { Token f1 = node.jjtGetFirstToken(); Token f2 = node.jjtGetLastToken(); sb.append(f1.image); String alias = ""; if (f1 != f2) { alias = f1.image; } CollectionAlias ca = fromMap.get(alias); List<Integer> list = map.get(ca); if (list == null) { list = new ArrayList<Integer>(); map.put(ca, list); } CollectionMetadata colMeta = SchemaMetadata.getInstance().getCollectionMetadata(ca.getCollectionName()); ResultSetColumn rsc = null; int columnId = -1; if (!"*".equals(f2.image)) { columnId = colMeta.getColumnId(f2.image); if (!list.contains(columnId)) { list.add(columnId); } if (isResultSet) { rsc = new ResultSetColumn(); rsc.ca = ca; rsc.columnId = columnId; } } else { synchronized (colMeta) { List<ColumnNameMeta> l1 = colMeta.getCollectionColumns(); Iterator<ColumnNameMeta> iter = l1.iterator(); while (iter.hasNext()) { ColumnNameMeta cc = iter.next(); columnId = cc.getCoulmnId(); if (!list.contains(columnId)) { list.add(columnId); } if (isResultSet) { rsc = new ResultSetColumn(); rsc.ca = ca; rsc.columnId = columnId; } } } } } if (node.children != null) { for (int i = 0; i < node.children.length; i++) { SimpleNode n = (SimpleNode) node.children[i]; getColumns(n, fromMap, map, resultSetColumns, isResultSet); } } } public AndExpression getAndExpression(SimpleNode startNode, Map<String, CollectionAlias> fromMap, List<ResultSetColumn> resultSetColumns) { SimpleNode selectNode = (SimpleNode) startNode.children[0]; SimpleNode filterNode = null; List<BasicExpression> list = new ArrayList<BasicExpression>(); for (int i = 0; i < selectNode.children.length; i++) { SimpleNode n = (SimpleNode) selectNode.children[i]; if (n.id == UQLParserTreeConstants.JJTFILTEREXPRESSION) { filterNode = n; break; } } if (filterNode == null) { return new AndExpression(new ArrayList<BasicExpression>()); } SimpleNode compareEq = (SimpleNode) filterNode.children[0]; for(int i = 0; i < compareEq.children.length; i++) { BasicExpression exp = buildExpression((SimpleNode) compareEq.children[i], fromMap, resultSetColumns); list.add(exp); } return new AndExpression(list); } private BasicExpression buildExpression(SimpleNode eqEq, Map<String, CollectionAlias> fromMap, List<ResultSetColumn> resultSetColumns) { SimpleNode left = null; SimpleNode right = null; int op = -1; for (int i = 0; i < eqEq.children.length; i++) { SimpleNode node = (SimpleNode) eqEq.children[i]; if (op == -1 && node.id == UQLParserTreeConstants.JJTCOMPAREEQUATION) { left = node; } else if (op >= 0 && node.id == UQLParserTreeConstants.JJTCOMPAREEQUATION) { right = node; } else { op = node.id; } } Operand l = buildOperand(left, fromMap, resultSetColumns); Operand r = buildOperand(right, fromMap, resultSetColumns); return new BasicExpression(l, r, op); } private Operand buildOperand(SimpleNode node, Map<String, CollectionAlias> fromMap, List<ResultSetColumn> resultSetColumns) { Map<CollectionAlias, List<Integer>> columns = getColumns(node, fromMap, resultSetColumns); int count = getColumnCount(columns); if (count == 1) { Iterator<CollectionAlias> iter = columns.keySet().iterator(); List<Integer> l = null; CollectionAlias ca = null; while (iter.hasNext()) { ca = iter.next(); l = columns.get(ca); } return new VariableOperand(ca, l.get(0), null); } else if (count == 0) { processMultiplicativeExpression(node); return new StaticOperand(new StringType((String) node.jjtGetValue())); } else { throw new RuntimeException("Invalid syntax"); } } private int getColumnCount(Map<CollectionAlias, List<Integer>> columns) { Iterator<List<Integer>> iter = columns.values().iterator(); int count = 0; while (iter.hasNext()) { List<Integer> list = iter.next(); count = count + list.size(); } return count; } public List<SimpleNode> getSelectStmts(SimpleNode start) { List<SimpleNode> list = new ArrayList<SimpleNode>(); if (start.id == UQLParserTreeConstants.JJTSELECTSTMT) { list.add(start); return list; } for (int i = 0; i < start.children.length; i++) { SimpleNode n = (SimpleNode) start.children[i]; if (n.id == UQLParserTreeConstants.JJTSELECTSTMT) { list.add(n); } } return list; } public SimpleNode getStmt(SimpleNode node) { if (node.id != UQLParserTreeConstants.JJTSTART) { return node; } return (SimpleNode) node.children[0]; } public static void dump(ExpressionNode node) { dump(node, ""); } public static void dump(ExpressionNode node, String indent) { System.out.println(indent); if (node == null) { return; } if (node.currentNode.id == UQLParserTreeConstants.JJTEQUALITYEQUATION) { for (int i = 0; i < node.currentNode.children.length; i++) { SimpleNode n = (SimpleNode) node.currentNode.children[i]; switch (n.id) { case UQLParserTreeConstants.JJTCOLUMNANDALIAS: QueryEvaluator.processCA(n); break; case UQLParserTreeConstants.JJTEQ: n.jjtSetValue("="); break; case UQLParserTreeConstants.JJTPLUS: n.jjtSetValue("+"); break; case UQLParserTreeConstants.JJTNUMBER: QueryEvaluator.processNumber(n); break; default: break; } System.out.print(n.jjtGetValue() + " "); } System.out.println(""); } else { for (int i = 0; i < node.andList.size(); i++) { dump(node.andList.get(i), indent+" "); } for (int i = 0; i < node.orList.size(); i++) { dump(node.orList.get(i), indent+" "); } } } }