/* *************************************************************************************** * 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.context.subselect; import com.espertech.esper.client.EventType; import com.espertech.esper.core.context.util.AgentInstanceContext; import com.espertech.esper.core.service.EPServicesContext; import com.espertech.esper.epl.agg.service.AggregationService; import com.espertech.esper.epl.agg.service.AggregationServiceFactoryDesc; import com.espertech.esper.epl.core.EngineImportService; import com.espertech.esper.epl.expression.core.ExprEvaluator; import com.espertech.esper.epl.expression.core.ExprValidationException; import com.espertech.esper.epl.expression.prev.ExprPreviousEvalStrategy; import com.espertech.esper.epl.expression.prev.ExprPreviousNode; import com.espertech.esper.epl.expression.prior.ExprPriorEvalStrategy; import com.espertech.esper.epl.expression.prior.ExprPriorNode; import com.espertech.esper.epl.join.hint.IndexHint; import com.espertech.esper.epl.join.table.EventTable; import com.espertech.esper.epl.lookup.*; import com.espertech.esper.epl.named.NamedWindowProcessor; import com.espertech.esper.epl.named.NamedWindowProcessorInstance; import com.espertech.esper.epl.named.NamedWindowRootView; import com.espertech.esper.epl.subquery.*; import com.espertech.esper.epl.table.mgmt.TableMetadata; import com.espertech.esper.epl.table.mgmt.TableService; import com.espertech.esper.epl.table.mgmt.TableServiceImpl; import com.espertech.esper.epl.table.mgmt.TableStateInstance; import com.espertech.esper.util.StopCallback; import com.espertech.esper.view.StatementStopCallback; import com.espertech.esper.view.StatementStopService; import com.espertech.esper.view.Viewable; import org.slf4j.Logger; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.List; import java.util.concurrent.locks.Lock; /** * Entry holding lookup resource references for use by {@link SubSelectActivationCollection}. */ public class SubSelectStrategyFactoryIndexShare implements SubSelectStrategyFactory { private final NamedWindowProcessor optionalNamedWindowProcessor; private final TableMetadata optionalTableMetadata; private final ExprEvaluator filterExprEval; private final AggregationServiceFactoryDesc aggregationServiceFactory; private final ExprEvaluator[] groupByKeys; private final TableService tableService; private SubordinateQueryPlanDesc queryPlan; public SubSelectStrategyFactoryIndexShare(final String statementName, int statementId, int subqueryNum, EventType[] outerEventTypesSelect, final NamedWindowProcessor optionalNamedWindowProcessor, TableMetadata optionalTableMetadata, boolean fullTableScan, IndexHint optionalIndexHint, SubordPropPlan joinedPropPlan, ExprEvaluator filterExprEval, AggregationServiceFactoryDesc aggregationServiceFactory, ExprEvaluator[] groupByKeys, TableService tableService, Annotation[] annotations, StatementStopService statementStopService, EngineImportService engineImportService) throws ExprValidationException { this.optionalNamedWindowProcessor = optionalNamedWindowProcessor; this.optionalTableMetadata = optionalTableMetadata; this.filterExprEval = filterExprEval; this.aggregationServiceFactory = aggregationServiceFactory; this.groupByKeys = groupByKeys; this.tableService = tableService; boolean isLogging; Logger log; if (optionalTableMetadata != null) { isLogging = optionalTableMetadata.isQueryPlanLogging(); log = TableServiceImpl.getQueryPlanLog(); queryPlan = SubordinateQueryPlanner.planSubquery(outerEventTypesSelect, joinedPropPlan, false, fullTableScan, optionalIndexHint, true, subqueryNum, false, optionalTableMetadata.getEventTableIndexMetadataRepo(), optionalTableMetadata.getUniqueKeyProps(), true, statementName, statementId, annotations); if (queryPlan != null) { for (int i = 0; i < queryPlan.getIndexDescs().length; i++) { optionalTableMetadata.addIndexReference(queryPlan.getIndexDescs()[i].getIndexName(), statementName); } } } else { isLogging = optionalNamedWindowProcessor.getRootView().isQueryPlanLogging(); log = NamedWindowRootView.getQueryPlanLog(); queryPlan = SubordinateQueryPlanner.planSubquery(outerEventTypesSelect, joinedPropPlan, false, fullTableScan, optionalIndexHint, true, subqueryNum, optionalNamedWindowProcessor.isVirtualDataWindow(), optionalNamedWindowProcessor.getEventTableIndexMetadataRepo(), optionalNamedWindowProcessor.getOptionalUniqueKeyProps(), false, statementName, statementId, annotations); if (queryPlan != null && queryPlan.getIndexDescs() != null) { SubordinateQueryPlannerUtil.addIndexMetaAndRef(queryPlan.getIndexDescs(), optionalNamedWindowProcessor.getEventTableIndexMetadataRepo(), statementName); statementStopService.addSubscriber(new StatementStopCallback() { public void statementStopped() { for (int i = 0; i < queryPlan.getIndexDescs().length; i++) { boolean last = optionalNamedWindowProcessor.getEventTableIndexMetadataRepo().removeIndexReference(queryPlan.getIndexDescs()[i].getIndexMultiKey(), statementName); if (last) { optionalNamedWindowProcessor.getEventTableIndexMetadataRepo().removeIndex(queryPlan.getIndexDescs()[i].getIndexMultiKey()); optionalNamedWindowProcessor.removeAllInstanceIndexes(queryPlan.getIndexDescs()[i].getIndexMultiKey()); } } } }); } } SubordinateQueryPlannerUtil.queryPlanLogOnSubq(isLogging, log, queryPlan, subqueryNum, annotations, engineImportService); } public SubSelectStrategyRealization instantiate(EPServicesContext services, Viewable viewableRoot, AgentInstanceContext agentInstanceContext, List<StopCallback> stopCallbackList, int subqueryNumber, boolean isRecoveringResilient) { SubselectAggregationPreprocessorBase subselectAggregationPreprocessor = null; AggregationService aggregationService = null; if (aggregationServiceFactory != null) { aggregationService = aggregationServiceFactory.getAggregationServiceFactory().makeService(agentInstanceContext, agentInstanceContext.getStatementContext().getEngineImportService(), true, subqueryNumber); if (groupByKeys == null) { if (filterExprEval == null) { subselectAggregationPreprocessor = new SubselectAggregationPreprocessorUnfilteredUngrouped(aggregationService, filterExprEval, null); } else { subselectAggregationPreprocessor = new SubselectAggregationPreprocessorFilteredUngrouped(aggregationService, filterExprEval, null); } } else { if (filterExprEval == null) { subselectAggregationPreprocessor = new SubselectAggregationPreprocessorUnfilteredGrouped(aggregationService, filterExprEval, groupByKeys); } else { subselectAggregationPreprocessor = new SubselectAggregationPreprocessorFilteredGrouped(aggregationService, filterExprEval, groupByKeys); } } } SubordTableLookupStrategy subqueryLookup; if (optionalNamedWindowProcessor != null) { NamedWindowProcessorInstance instance = optionalNamedWindowProcessor.getProcessorInstance(agentInstanceContext); if (queryPlan == null) { if (instance.getRootViewInstance().isQueryPlanLogging() && NamedWindowRootView.getQueryPlanLog().isInfoEnabled()) { NamedWindowRootView.getQueryPlanLog().info("shared, full table scan"); } subqueryLookup = new SubordFullTableScanLookupStrategyLocking(instance.getRootViewInstance().getDataWindowContents(), agentInstanceContext.getEpStatementAgentInstanceHandle().getStatementAgentInstanceLock()); } else { EventTable[] tables = null; if (!optionalNamedWindowProcessor.isVirtualDataWindow()) { tables = SubordinateQueryPlannerUtil.realizeTables(queryPlan.getIndexDescs(), instance.getRootViewInstance().getEventType(), instance.getRootViewInstance().getIndexRepository(), instance.getRootViewInstance().getDataWindowContents(), agentInstanceContext, isRecoveringResilient); } SubordTableLookupStrategy strategy = queryPlan.getLookupStrategyFactory().makeStrategy(tables, instance.getRootViewInstance().getVirtualDataWindow()); subqueryLookup = new SubordIndexedTableLookupStrategyLocking(strategy, instance.getTailViewInstance().getAgentInstanceContext().getAgentInstanceLock()); } } else { TableStateInstance state = tableService.getState(optionalTableMetadata.getTableName(), agentInstanceContext.getAgentInstanceId()); Lock lock = agentInstanceContext.getStatementContext().isWritesToTables() ? state.getTableLevelRWLock().writeLock() : state.getTableLevelRWLock().readLock(); if (queryPlan == null) { subqueryLookup = new SubordFullTableScanTableLookupStrategy(lock, state.getIterableTableScan()); } else { EventTable[] indexes = new EventTable[queryPlan.getIndexDescs().length]; for (int i = 0; i < indexes.length; i++) { indexes[i] = state.getIndexRepository().getIndexByDesc(queryPlan.getIndexDescs()[i].getIndexMultiKey()); } subqueryLookup = queryPlan.getLookupStrategyFactory().makeStrategy(indexes, null); subqueryLookup = new SubordIndexedTableLookupTableStrategy(subqueryLookup, lock); } } return new SubSelectStrategyRealization(subqueryLookup, subselectAggregationPreprocessor, aggregationService, Collections.<ExprPriorNode, ExprPriorEvalStrategy>emptyMap(), Collections.<ExprPreviousNode, ExprPreviousEvalStrategy>emptyMap(), null, null); } }