/* * ************************************************************************************* * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * * ************************************************************************************* */ package com.espertech.esper.epl.spec.util; import com.espertech.esper.client.EPException; import com.espertech.esper.epl.expression.*; import com.espertech.esper.epl.spec.*; import com.espertech.esper.pattern.*; import java.util.ArrayList; import java.util.List; public class StatementSpecRawAnalyzer { public static List<FilterSpecRaw> analyzeFilters(StatementSpecRaw spec) throws ExprValidationException { List<FilterSpecRaw> result = new ArrayList<FilterSpecRaw>(); addFilters(spec, result); ExprNodeSubselectDeclaredDotVisitor subselects = walkSubselectAndDeclaredDotExpr(spec); for (ExprSubselectNode subselect : subselects.getSubselects()) { addFilters(subselect.getStatementSpecRaw(), result); } return result; } private static void addFilters(StatementSpecRaw spec, List<FilterSpecRaw> filters) { for (StreamSpecRaw raw : spec.getStreamSpecs()) { if (raw instanceof FilterStreamSpecRaw) { FilterStreamSpecRaw r = (FilterStreamSpecRaw) raw; filters.add(r.getRawFilterSpec()); } if (raw instanceof PatternStreamSpecRaw) { PatternStreamSpecRaw r = (PatternStreamSpecRaw) raw; EvalNodeAnalysisResult evalNodeAnalysisResult = EvalNodeUtil.recursiveAnalyzeChildNodes(r.getEvalFactoryNode()); List<EvalFilterFactoryNode> filterNodes = evalNodeAnalysisResult.getFilterNodes(); for (EvalFilterFactoryNode filterNode : filterNodes) { filters.add(filterNode.getRawFilterSpec()); } } } } public static ExprNodeSubselectDeclaredDotVisitor walkSubselectAndDeclaredDotExpr(StatementSpecRaw spec) throws ExprValidationException { // Look for expressions with sub-selects in select expression list and filter expression // Recursively compile the statement within the statement. ExprNodeSubselectDeclaredDotVisitor visitor = new ExprNodeSubselectDeclaredDotVisitor(); for (SelectClauseElementRaw raw : spec.getSelectClauseSpec().getSelectExprList()) { if (raw instanceof SelectClauseExprRawSpec) { SelectClauseExprRawSpec rawExpr = (SelectClauseExprRawSpec) raw; rawExpr.getSelectExpression().accept(visitor); } else { continue; } } if (spec.getFilterRootNode() != null) { spec.getFilterRootNode().accept(visitor); } if (spec.getUpdateDesc() != null) { if (spec.getUpdateDesc().getOptionalWhereClause() != null) { spec.getUpdateDesc().getOptionalWhereClause().accept(visitor); } for (OnTriggerSetAssignment assignment : spec.getUpdateDesc().getAssignments()) { assignment.getExpression().accept(visitor); } } if (spec.getOnTriggerDesc() != null) { visitSubselectOnTrigger(spec.getOnTriggerDesc(), visitor); } // Determine pattern-filter subqueries for (StreamSpecRaw streamSpecRaw : spec.getStreamSpecs()) { if (streamSpecRaw instanceof PatternStreamSpecRaw) { PatternStreamSpecRaw patternStreamSpecRaw = (PatternStreamSpecRaw) streamSpecRaw; EvalNodeAnalysisResult analysisResult = EvalNodeUtil.recursiveAnalyzeChildNodes(patternStreamSpecRaw.getEvalFactoryNode()); for (EvalFactoryNode evalNode : analysisResult.getActiveNodes()) { if (evalNode instanceof EvalFilterFactoryNode) { EvalFilterFactoryNode filterNode = (EvalFilterFactoryNode) evalNode; for (ExprNode filterExpr : filterNode.getRawFilterSpec().getFilterExpressions()) { filterExpr.accept(visitor); } } else if (evalNode instanceof EvalObserverFactoryNode) { int beforeCount = visitor.getSubselects().size(); EvalObserverFactoryNode observerNode = (EvalObserverFactoryNode) evalNode; for (ExprNode param : observerNode.getPatternObserverSpec().getObjectParameters()) { param.accept(visitor); } if (visitor.getSubselects().size() != beforeCount) { throw new ExprValidationException("Subselects are not allowed within pattern observer parameters, please consider using a variable instead"); } } } } } // Determine filter streams for (StreamSpecRaw rawSpec : spec.getStreamSpecs()) { if (rawSpec instanceof FilterStreamSpecRaw) { FilterStreamSpecRaw raw = (FilterStreamSpecRaw) rawSpec; for (ExprNode filterExpr : raw.getRawFilterSpec().getFilterExpressions()) { filterExpr.accept(visitor); } } } return visitor; } private static void visitSubselectOnTrigger(OnTriggerDesc onTriggerDesc, ExprNodeSubselectDeclaredDotVisitor visitor) { if (onTriggerDesc instanceof OnTriggerWindowUpdateDesc) { OnTriggerWindowUpdateDesc updates = (OnTriggerWindowUpdateDesc) onTriggerDesc; for (OnTriggerSetAssignment assignment : updates.getAssignments()) { assignment.getExpression().accept(visitor); } } else if (onTriggerDesc instanceof OnTriggerSetDesc) { OnTriggerSetDesc sets = (OnTriggerSetDesc) onTriggerDesc; for (OnTriggerSetAssignment assignment : sets.getAssignments()) { assignment.getExpression().accept(visitor); } } else if (onTriggerDesc instanceof OnTriggerSplitStreamDesc) { OnTriggerSplitStreamDesc splits = (OnTriggerSplitStreamDesc) onTriggerDesc; for (OnTriggerSplitStream split : splits.getSplitStreams()) { if (split.getWhereClause() != null) { split.getWhereClause().accept(visitor); } if (split.getSelectClause().getSelectExprList() != null) { for (SelectClauseElementRaw element : split.getSelectClause().getSelectExprList()) { if (element instanceof SelectClauseExprRawSpec) { SelectClauseExprRawSpec selectExpr = (SelectClauseExprRawSpec) element; selectExpr.getSelectExpression().accept(visitor); } } } } } else if (onTriggerDesc instanceof OnTriggerMergeDesc) { OnTriggerMergeDesc merge = (OnTriggerMergeDesc) onTriggerDesc; for (OnTriggerMergeMatched matched : merge.getItems()) { if (matched.getOptionalMatchCond() != null) { matched.getOptionalMatchCond().accept(visitor); } for (OnTriggerMergeAction action : matched.getActions()) { if (action.getOptionalWhereClause() != null) { action.getOptionalWhereClause().accept(visitor); } if (action instanceof OnTriggerMergeActionUpdate) { OnTriggerMergeActionUpdate update = (OnTriggerMergeActionUpdate) action; for (OnTriggerSetAssignment assignment : update.getAssignments()) { assignment.getExpression().accept(visitor); } } if (action instanceof OnTriggerMergeActionInsert) { OnTriggerMergeActionInsert insert = (OnTriggerMergeActionInsert) action; for (SelectClauseElementRaw element : insert.getSelectClause()) { if (element instanceof SelectClauseExprRawSpec) { SelectClauseExprRawSpec selectExpr = (SelectClauseExprRawSpec) element; selectExpr.getSelectExpression().accept(visitor); } } } } } } } public static List<ExprNode> collectExpressionsShallow(StatementSpecRaw raw) { final List<ExprNode> expressions = new ArrayList<ExprNode>(); if (raw.getExpressionDeclDesc() != null) { for (ExpressionDeclItem decl : raw.getExpressionDeclDesc().getExpressions()) { expressions.add(decl.getInner()); } } if (raw.getCreateExpressionDesc() != null) { if (raw.getCreateExpressionDesc().getExpression() != null) { expressions.add(raw.getCreateExpressionDesc().getExpression().getInner()); } } if (raw.getCreateContextDesc() != null) { ContextDetail detail = raw.getCreateContextDesc().getContextDetail(); if (detail instanceof ContextDetailPartitioned) { ContextDetailPartitioned ks = (ContextDetailPartitioned) detail; for (ContextDetailPartitionItem item : ks.getItems()) { if (item.getFilterSpecRaw().getFilterExpressions() != null) { expressions.addAll(item.getFilterSpecRaw().getFilterExpressions()); } } } else if (detail instanceof ContextDetailCategory) { ContextDetailCategory cat = (ContextDetailCategory) detail; for (ContextDetailCategoryItem item : cat.getItems()) { if (item.getExpression() != null) { expressions.add(item.getExpression()); } } if (cat.getFilterSpecRaw().getFilterExpressions() != null) { expressions.addAll(cat.getFilterSpecRaw().getFilterExpressions()); } } else if (detail instanceof ContextDetailInitiatedTerminated) { ContextDetailInitiatedTerminated ts = (ContextDetailInitiatedTerminated) detail; collectExpressions(expressions, ts.getStart()); collectExpressions(expressions, ts.getEnd()); } else { throw new EPException("Failed to obtain expressions from context detail " + detail); } } if (raw.getCreateVariableDesc() != null) { ExprNode expr = raw.getCreateVariableDesc().getAssignment(); if (expr != null) { expressions.add(expr); } } if (raw.getCreateWindowDesc() != null) { ExprNode expr = raw.getCreateWindowDesc().getInsertFilter(); if (expr != null) { expressions.add(expr); } for (ViewSpec view : raw.getCreateWindowDesc().getViewSpecs()) { expressions.addAll(view.getObjectParameters()); } } if (raw.getUpdateDesc() != null) { if (raw.getUpdateDesc().getOptionalWhereClause() != null) { expressions.add(raw.getUpdateDesc().getOptionalWhereClause()); } if (raw.getUpdateDesc().getAssignments() != null) { for (OnTriggerSetAssignment pair : raw.getUpdateDesc().getAssignments()) { expressions.add(pair.getExpression()); } } } // on-expr if (raw.getOnTriggerDesc() != null) { if (raw.getOnTriggerDesc() instanceof OnTriggerSplitStreamDesc) { OnTriggerSplitStreamDesc onSplit = (OnTriggerSplitStreamDesc) raw.getOnTriggerDesc(); for (OnTriggerSplitStream item : onSplit.getSplitStreams()) { if (item.getSelectClause() != null) { addSelectClause(expressions, item.getSelectClause().getSelectExprList()); } if (item.getWhereClause() != null) { expressions.add(item.getWhereClause()); } } } if (raw.getOnTriggerDesc() instanceof OnTriggerSetDesc) { OnTriggerSetDesc onSet = (OnTriggerSetDesc) raw.getOnTriggerDesc(); if (onSet.getAssignments() != null) { for (OnTriggerSetAssignment aitem : onSet.getAssignments()) { expressions.add(aitem.getExpression()); } } } if (raw.getOnTriggerDesc() instanceof OnTriggerWindowUpdateDesc) { OnTriggerWindowUpdateDesc onUpdate = (OnTriggerWindowUpdateDesc) raw.getOnTriggerDesc(); if (onUpdate.getAssignments() != null) { for (OnTriggerSetAssignment bitem : onUpdate.getAssignments()) { expressions.add(bitem.getExpression()); } } } if (raw.getOnTriggerDesc() instanceof OnTriggerMergeDesc) { OnTriggerMergeDesc onMerge = (OnTriggerMergeDesc) raw.getOnTriggerDesc(); for (OnTriggerMergeMatched item : onMerge.getItems()) { if (item.getOptionalMatchCond() != null) { expressions.add(item.getOptionalMatchCond()); } for (OnTriggerMergeAction action : item.getActions()) { if (action instanceof OnTriggerMergeActionDelete) { OnTriggerMergeActionDelete delete = (OnTriggerMergeActionDelete) action; if (delete.getOptionalWhereClause() != null) { expressions.add(delete.getOptionalWhereClause()); } } else if (action instanceof OnTriggerMergeActionUpdate) { OnTriggerMergeActionUpdate update = (OnTriggerMergeActionUpdate) action; if (update.getOptionalWhereClause() != null) { expressions.add(update.getOptionalWhereClause()); } for (OnTriggerSetAssignment assignment : update.getAssignments()) { expressions.add(assignment.getExpression()); } } else if (action instanceof OnTriggerMergeActionInsert) { OnTriggerMergeActionInsert insert = (OnTriggerMergeActionInsert) action; if (insert.getOptionalWhereClause() != null) { expressions.add(insert.getOptionalWhereClause()); } addSelectClause(expressions, insert.getSelectClause()); } } } } } // select clause if (raw.getSelectClauseSpec() != null) { addSelectClause(expressions, raw.getSelectClauseSpec().getSelectExprList()); } // from clause if (raw.getStreamSpecs() != null) { for (StreamSpecRaw stream : raw.getStreamSpecs()) { // filter stream if (stream instanceof FilterStreamSpecRaw) { FilterStreamSpecRaw filterStream = (FilterStreamSpecRaw) stream; FilterSpecRaw filter = filterStream.getRawFilterSpec(); if ((filter != null) && (filter.getFilterExpressions() != null)){ expressions.addAll(filter.getFilterExpressions()); } if ((filter != null) && (filter.getOptionalPropertyEvalSpec() != null)) { for (PropertyEvalAtom contained : filter.getOptionalPropertyEvalSpec().getAtoms()) { addSelectClause(expressions, contained.getOptionalSelectClause() == null ? null : contained.getOptionalSelectClause().getSelectExprList()); if (contained.getOptionalWhereClause() != null) { expressions.add(contained.getOptionalWhereClause()); } } } } // pattern stream if (stream instanceof PatternStreamSpecRaw) { PatternStreamSpecRaw patternStream = (PatternStreamSpecRaw) stream; collectPatternExpressions(expressions, patternStream.getEvalFactoryNode()); } // method stream if (stream instanceof MethodStreamSpec) { MethodStreamSpec methodStream = (MethodStreamSpec) stream; if (methodStream.getExpressions() != null) { expressions.addAll(methodStream.getExpressions()); } } if (stream.getViewSpecs() != null) { for (ViewSpec view : stream.getViewSpecs()) { expressions.addAll(view.getObjectParameters()); } } } if (raw.getOuterJoinDescList() != null) { for (OuterJoinDesc q : raw.getOuterJoinDescList()) { if (q.getOptLeftNode() != null) { expressions.add(q.getOptLeftNode()); expressions.add(q.getOptRightNode()); for (ExprIdentNode ident : q.getAdditionalLeftNodes()) { expressions.add(ident); } for (ExprIdentNode ident : q.getAdditionalRightNodes()) { expressions.add(ident); } } } } } if (raw.getFilterRootNode() != null) { expressions.add(raw.getFilterRootNode()); } if (raw.getGroupByExpressions() != null) { expressions.addAll(raw.getGroupByExpressions()); } if (raw.getHavingExprRootNode() != null) { expressions.add(raw.getHavingExprRootNode()); } if (raw.getOutputLimitSpec() != null) { if (raw.getOutputLimitSpec().getWhenExpressionNode() != null) { expressions.add(raw.getOutputLimitSpec().getWhenExpressionNode()); } if (raw.getOutputLimitSpec().getThenExpressions() != null) { for (OnTriggerSetAssignment thenAssign : raw.getOutputLimitSpec().getThenExpressions()) { expressions.add(thenAssign.getExpression()); } } if (raw.getOutputLimitSpec().getCrontabAtSchedule() != null) { expressions.addAll(raw.getOutputLimitSpec().getCrontabAtSchedule()); } if (raw.getOutputLimitSpec().getTimePeriodExpr() != null) { expressions.add(raw.getOutputLimitSpec().getTimePeriodExpr()); } if (raw.getOutputLimitSpec().getAfterTimePeriodExpr() != null) { expressions.add(raw.getOutputLimitSpec().getAfterTimePeriodExpr()); } } if (raw.getOrderByList() != null) { for (OrderByItem orderByElement : raw.getOrderByList()) { expressions.add(orderByElement.getExprNode()); } } if (raw.getMatchRecognizeSpec() != null) { if (raw.getMatchRecognizeSpec().getPartitionByExpressions() != null) { expressions.addAll(raw.getMatchRecognizeSpec().getPartitionByExpressions()); } for (MatchRecognizeMeasureItem selectItemMR : raw.getMatchRecognizeSpec().getMeasures()) { expressions.add(selectItemMR.getExpr()); } for (MatchRecognizeDefineItem define : raw.getMatchRecognizeSpec().getDefines()) { expressions.add(define.getExpression()); } if (raw.getMatchRecognizeSpec().getInterval() != null) { if (raw.getMatchRecognizeSpec().getInterval().getTimePeriodExpr() != null) { expressions.add(raw.getMatchRecognizeSpec().getInterval().getTimePeriodExpr()); } } } if (raw.getForClauseSpec() != null) { for (ForClauseItemSpec item : raw.getForClauseSpec().getClauses()) { if (item.getExpressions() != null) { expressions.addAll(item.getExpressions()); } } } return expressions; } private static void collectExpressions(List<ExprNode> expressions, ContextDetailCondition endpoint) { if (endpoint instanceof ContextDetailConditionCrontab) { ContextDetailConditionCrontab crontab = (ContextDetailConditionCrontab) endpoint; expressions.addAll(crontab.getCrontab()); } } private static void addSelectClause(List<ExprNode> expressions, List<SelectClauseElementRaw> selectClause) { if (selectClause == null) { return; } for (SelectClauseElementRaw selement : selectClause) { if (!(selement instanceof SelectClauseExprRawSpec)) { continue; } SelectClauseExprRawSpec sexpr = (SelectClauseExprRawSpec) selement; expressions.add(sexpr.getSelectExpression()); } } private static void collectPatternExpressions(final List<ExprNode> expressions, EvalFactoryNode patternExpression) { if (patternExpression instanceof EvalFilterFactoryNode) { EvalFilterFactoryNode filter = (EvalFilterFactoryNode) patternExpression; if (filter.getRawFilterSpec().getFilterExpressions() != null) { expressions.addAll(filter.getRawFilterSpec().getFilterExpressions()); } } for (EvalFactoryNode child : patternExpression.getChildNodes()) { collectPatternExpressions(expressions, child); } } }