/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * 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.core.service; import com.espertech.esper.epl.expression.core.ExprNode; import com.espertech.esper.epl.expression.core.ExprValidationException; import com.espertech.esper.epl.expression.visitor.ExprNodeSubselectDeclaredDotVisitor; import com.espertech.esper.epl.spec.*; import com.espertech.esper.epl.table.mgmt.TableService; import com.espertech.esper.filter.FilterSpecCompiled; import com.espertech.esper.filter.FilterSpecParam; import com.espertech.esper.filter.FilterSpecParamExprNode; import com.espertech.esper.pattern.*; import java.util.ArrayList; import java.util.List; public class StatementLifecycleSvcUtil { public static void assignFilterSpecIds(FilterSpecCompiled filterSpec, FilterSpecCompiled[] filterSpecsAll) { for (int path = 0; path < filterSpec.getParameters().length; path++) { for (FilterSpecParam param : filterSpec.getParameters()[path]) { if (param instanceof FilterSpecParamExprNode) { int index = filterSpec.getFilterSpecIndexAmongAll(filterSpecsAll); FilterSpecParamExprNode exprNode = (FilterSpecParamExprNode) param; exprNode.setFilterSpecId(index); exprNode.setFilterSpecParamPathNum(path); } } } } public static void walkStatement(StatementSpecRaw spec, ExprNodeSubselectDeclaredDotVisitor visitor) throws ExprValidationException { // Look for expressions with sub-selects in select expression list and filter expression // Recursively compile the statement within the statement. 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.getHavingExprRootNode() != null) { spec.getHavingExprRootNode().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"); } } } } } // walk streams walkStreamSpecs(spec, visitor); } public static void walkStreamSpecs(StatementSpecRaw spec, ExprNodeSubselectDeclaredDotVisitor visitor) { // 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); } } if (rawSpec instanceof PatternStreamSpecRaw) { PatternStreamSpecRaw patternStreamSpecRaw = (PatternStreamSpecRaw) rawSpec; 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); } } } } } } 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 SelectClauseSpecCompiled compileSelectClause(SelectClauseSpecRaw spec) { List<SelectClauseElementCompiled> selectElements = new ArrayList<SelectClauseElementCompiled>(); for (SelectClauseElementRaw raw : spec.getSelectExprList()) { if (raw instanceof SelectClauseExprRawSpec) { SelectClauseExprRawSpec rawExpr = (SelectClauseExprRawSpec) raw; selectElements.add(new SelectClauseExprCompiledSpec(rawExpr.getSelectExpression(), rawExpr.getOptionalAsName(), rawExpr.getOptionalAsName(), rawExpr.isEvents())); } else if (raw instanceof SelectClauseStreamRawSpec) { SelectClauseStreamRawSpec rawExpr = (SelectClauseStreamRawSpec) raw; selectElements.add(new SelectClauseStreamCompiledSpec(rawExpr.getStreamName(), rawExpr.getOptionalAsName())); } else if (raw instanceof SelectClauseElementWildcard) { SelectClauseElementWildcard wildcard = (SelectClauseElementWildcard) raw; selectElements.add(wildcard); } else { throw new IllegalStateException("Unexpected select clause element class : " + raw.getClass().getName()); } } return new SelectClauseSpecCompiled(selectElements.toArray(new SelectClauseElementCompiled[selectElements.size()]), spec.isDistinct()); } public static boolean isWritesToTables(StatementSpecRaw statementSpec, TableService tableService) { // determine if writing to a table: // insert-into (single) if (statementSpec.getInsertIntoDesc() != null) { if (isTable(statementSpec.getInsertIntoDesc().getEventTypeName(), tableService)) { return true; } } // into-table if (statementSpec.getIntoTableSpec() != null) { return true; } // triggers if (statementSpec.getOnTriggerDesc() != null) { OnTriggerDesc onTriggerDesc = statementSpec.getOnTriggerDesc(); // split-stream insert-into if (onTriggerDesc.getOnTriggerType() == OnTriggerType.ON_SPLITSTREAM) { OnTriggerSplitStreamDesc split = (OnTriggerSplitStreamDesc) onTriggerDesc; for (OnTriggerSplitStream stream : split.getSplitStreams()) { if (stream.getInsertInto() != null && isTable(stream.getInsertInto().getEventTypeName(), tableService)) { return true; } } } // on-delete/update/merge/on-selectdelete if (onTriggerDesc instanceof OnTriggerWindowDesc) { OnTriggerWindowDesc window = (OnTriggerWindowDesc) onTriggerDesc; if (onTriggerDesc.getOnTriggerType() == OnTriggerType.ON_DELETE || onTriggerDesc.getOnTriggerType() == OnTriggerType.ON_UPDATE || onTriggerDesc.getOnTriggerType() == OnTriggerType.ON_MERGE || window.isDeleteAndSelect()) { if (isTable(window.getWindowName(), tableService)) { return true; } } } // on-merge with insert-action if (onTriggerDesc instanceof OnTriggerMergeDesc) { OnTriggerMergeDesc merge = (OnTriggerMergeDesc) onTriggerDesc; for (OnTriggerMergeMatched item : merge.getItems()) { for (OnTriggerMergeAction action : item.getActions()) { if (action instanceof OnTriggerMergeActionInsert) { OnTriggerMergeActionInsert insert = (OnTriggerMergeActionInsert) action; if (insert.getOptionalStreamName() != null && isTable(insert.getOptionalStreamName(), tableService)) { return true; } } } } } } // end of trigger handling // fire-and-forget insert/update/delete if (statementSpec.getFireAndForgetSpec() != null) { FireAndForgetSpec faf = statementSpec.getFireAndForgetSpec(); if (faf instanceof FireAndForgetSpecDelete || faf instanceof FireAndForgetSpecInsert || faf instanceof FireAndForgetSpecUpdate) { if (statementSpec.getStreamSpecs().size() == 1) { return isTable(((FilterStreamSpecRaw) statementSpec.getStreamSpecs().get(0)).getRawFilterSpec().getEventTypeName(), tableService); } } } return false; } private static boolean isTable(String name, TableService tableService) { return tableService.getTableMetadata(name) != null; } }