package org.openanzo.glitter.query.validator; import java.util.LinkedList; import org.openanzo.glitter.expression.AggregateFunction; import org.openanzo.glitter.query.OrderingCondition; import org.openanzo.glitter.query.QueryInformation; import org.openanzo.glitter.query.QueryValidator; import org.openanzo.glitter.syntax.abstrakt.Expression; import org.openanzo.glitter.syntax.abstrakt.FunctionCall; import org.openanzo.glitter.syntax.abstrakt.TreeNode; /** * Checks that functions used in FILTERs and ORDER BY and LET clauses are scalar (not aggregate) functions. * * @author lee <lee@cambridgesemantics.com> * */ public class ScalarFunctionValidator implements QueryValidator { private AggregateFunction f = null; public String getValidationError() { return "Aggregate function '" + f + "' is used outside a SELECT clause"; } public String getValidatorDescription() { return "Checks that aggregate functions are not used where only scalar functions are allowed"; } private AggregateFunction findFirstAggregateFunction(Expression e) { AggregateFunction af = null; if (e instanceof FunctionCall) { FunctionCall fc = (FunctionCall) e; if (fc.getFunction() instanceof AggregateFunction) return (AggregateFunction) fc.getFunction(); for (Expression arg : fc.getArguments()) if ((af = findFirstAggregateFunction(arg)) != null) return af; } return null; } public boolean validateQuery(QueryInformation query) { AggregateFunction af = null; for (OrderingCondition oc : query.getOrderingConditions()) { if ((af = findFirstAggregateFunction(oc.getCondition())) != null) { this.f = af; return false; } } LinkedList<TreeNode> nodes = new LinkedList<TreeNode>(); nodes.add(query.getQueryPattern()); while (!nodes.isEmpty()) { TreeNode tn = nodes.removeFirst(); if (tn != null) { if (tn.getFilters() != null) for (Expression e : tn.getFilters()) { if ((af = findFirstAggregateFunction(e)) != null) { this.f = af; return false; } } if (tn.getChildren() != null) { nodes.addAll(tn.getChildren()); } } } return true; } }