com.espertech.esper.epl.lookup.SubordinateQueryPlannerUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.espertech.esper.epl.lookup.SubordinateQueryPlannerUtil.java

Source

/**************************************************************************************
 * Copyright (C) 2006-2015 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.epl.lookup;

import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.epl.expression.core.ExprEvaluator;
import com.espertech.esper.epl.expression.core.ExprValidationException;
import com.espertech.esper.epl.join.plan.CoercionDesc;
import com.espertech.esper.epl.join.table.EventTable;
import com.espertech.esper.epl.join.table.EventTableAndNamePair;
import com.espertech.esper.epl.join.table.EventTableUtil;
import com.espertech.esper.epl.join.util.*;
import com.espertech.esper.util.CollectionUtil;
import com.espertech.esper.util.JavaClassHelper;
import org.apache.commons.logging.Log;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SubordinateQueryPlannerUtil {
    public static void queryPlanLogOnExpr(boolean queryPlanLogging, Log queryPlanLog,
            SubordinateWMatchExprQueryPlanResult strategy, Annotation[] annotations) {
        QueryPlanIndexHook hook = QueryPlanIndexHookUtil.getHook(annotations);
        if (queryPlanLogging && (queryPlanLog.isInfoEnabled() || hook != null)) {
            String prefix = "On-Expr ";
            queryPlanLog.info(prefix + "strategy " + strategy.getFactory().toQueryPlan());
            if (strategy.getIndexDescs() == null) {
                queryPlanLog.info(prefix + "full table scan");
            } else {
                for (int i = 0; i < strategy.getIndexDescs().length; i++) {
                    String indexName = strategy.getIndexDescs()[i].getIndexName();
                    String indexText = indexName != null ? "index " + indexName + " " : "(implicit) (" + i + ")";
                    queryPlanLog.info(prefix + indexText);
                }
            }
            if (hook != null) {
                IndexNameAndDescPair[] pairs = getPairs(strategy.getIndexDescs());
                SubordTableLookupStrategyFactory inner = strategy.getFactory().getOptionalInnerStrategy();
                hook.infraOnExpr(
                        new QueryPlanIndexDescOnExpr(pairs, strategy.getFactory().getClass().getSimpleName(),
                                inner == null ? null : inner.getClass().getSimpleName()));
            }
        }
    }

    public static void queryPlanLogOnSubq(boolean queryPlanLogging, Log queryPlanLog, SubordinateQueryPlanDesc plan,
            int subqueryNum, Annotation[] annotations) {
        QueryPlanIndexHook hook = QueryPlanIndexHookUtil.getHook(annotations);
        if (queryPlanLogging && (queryPlanLog.isInfoEnabled() || hook != null)) {
            String prefix = "Subquery " + subqueryNum + " ";
            String strategy = (plan == null || plan.getLookupStrategyFactory() == null) ? "table scan"
                    : plan.getLookupStrategyFactory().toQueryPlan();
            queryPlanLog.info(prefix + "strategy " + strategy);
            if (plan != null) {
                if (plan.getIndexDescs() != null) {
                    for (int i = 0; i < plan.getIndexDescs().length; i++) {
                        String indexName = plan.getIndexDescs()[i].getIndexName();
                        String indexText = indexName != null ? "index " + indexName + " " : "(implicit) ";
                        queryPlanLog.info(prefix + "shared index");
                        queryPlanLog.info(prefix + indexText);
                    }
                }
            }
            if (hook != null) {
                IndexNameAndDescPair[] pairs = plan == null ? new IndexNameAndDescPair[0]
                        : getPairs(plan.getIndexDescs());
                String factory = plan == null ? null : plan.getLookupStrategyFactory().getClass().getSimpleName();
                hook.subquery(new QueryPlanIndexDescSubquery(pairs, subqueryNum, factory));
            }
        }
    }

    private static IndexNameAndDescPair[] getPairs(SubordinateQueryIndexDesc[] indexDescs) {
        if (indexDescs == null) {
            return null;
        }
        IndexNameAndDescPair[] pairs = new IndexNameAndDescPair[indexDescs.length];
        for (int i = 0; i < indexDescs.length; i++) {
            SubordinateQueryIndexDesc index = indexDescs[i];
            pairs[i] = new IndexNameAndDescPair(index.getIndexName(), index.getIndexMultiKey().toQueryPlan());
        }
        return pairs;
    }

    public static SubordinateQueryPlannerIndexPropListPair toListOfHashedAndBtreeProps(
            String[] hashIndexPropsProvided, Class[] hashIndexCoercionType, String[] rangeIndexPropsProvided,
            Class[] rangeIndexCoercionType) {
        List<IndexedPropDesc> hashedProps = new ArrayList<IndexedPropDesc>();
        List<IndexedPropDesc> btreeProps = new ArrayList<IndexedPropDesc>();
        for (int i = 0; i < hashIndexPropsProvided.length; i++) {
            hashedProps.add(new IndexedPropDesc(hashIndexPropsProvided[i], hashIndexCoercionType[i]));
        }
        for (int i = 0; i < rangeIndexPropsProvided.length; i++) {
            btreeProps.add(new IndexedPropDesc(rangeIndexPropsProvided[i], rangeIndexCoercionType[i]));
        }
        return new SubordinateQueryPlannerIndexPropListPair(hashedProps, btreeProps);
    }

    /**
     * Given an index with a defined set of hash(equals) and range(btree) props and uniqueness flag,
     * and given a list of indexable properties and accessors for both hash and range,
     * return the ordered keys and coercion information.
     * @param indexMultiKey index definition
     * @param hashIndexPropsProvided hash indexable properties
     * @param hashJoinedProps keys for hash indexable properties
     * @param rangeIndexPropsProvided btree indexable properties
     * @param rangeJoinedProps keys for btree indexable properties
     * @return ordered set of key information
     */
    public static IndexKeyInfo compileIndexKeyInfo(IndexMultiKey indexMultiKey, String[] hashIndexPropsProvided,
            SubordPropHashKey[] hashJoinedProps, String[] rangeIndexPropsProvided,
            SubordPropRangeKey[] rangeJoinedProps) {

        // map the order of indexed columns (key) to the key information available
        IndexedPropDesc[] indexedKeyProps = indexMultiKey.getHashIndexedProps();
        boolean isCoerceHash = false;
        SubordPropHashKey[] hashesDesc = new SubordPropHashKey[indexedKeyProps.length];
        Class[] hashPropCoercionTypes = new Class[indexedKeyProps.length];

        for (int i = 0; i < indexedKeyProps.length; i++) {
            String indexField = indexedKeyProps[i].getIndexPropName();
            int index = CollectionUtil.findItem(hashIndexPropsProvided, indexField);
            if (index == -1) {
                throw new IllegalStateException("Could not find index property for lookup '" + indexedKeyProps[i]);
            }
            hashesDesc[i] = hashJoinedProps[index];
            hashPropCoercionTypes[i] = indexedKeyProps[i].getCoercionType();
            ExprEvaluator evaluatorHashkey = hashesDesc[i].getHashKey().getKeyExpr().getExprEvaluator();
            if (evaluatorHashkey != null
                    && JavaClassHelper.getBoxedType(indexedKeyProps[i].getCoercionType()) != JavaClassHelper
                            .getBoxedType(evaluatorHashkey.getType())) { // we allow null evaluator
                isCoerceHash = true;
            }
        }

        // map the order of range columns (range) to the range information available
        indexedKeyProps = indexMultiKey.getRangeIndexedProps();
        SubordPropRangeKey[] rangesDesc = new SubordPropRangeKey[indexedKeyProps.length];
        Class[] rangePropCoercionTypes = new Class[indexedKeyProps.length];
        boolean isCoerceRange = false;
        for (int i = 0; i < indexedKeyProps.length; i++) {
            String indexField = indexedKeyProps[i].getIndexPropName();
            int index = CollectionUtil.findItem(rangeIndexPropsProvided, indexField);
            if (index == -1) {
                throw new IllegalStateException("Could not find range property for lookup '" + indexedKeyProps[i]);
            }
            rangesDesc[i] = rangeJoinedProps[index];
            rangePropCoercionTypes[i] = rangeJoinedProps[index].getCoercionType();
            if (JavaClassHelper.getBoxedType(indexedKeyProps[i].getCoercionType()) != JavaClassHelper
                    .getBoxedType(rangePropCoercionTypes[i])) {
                isCoerceRange = true;
            }
        }

        return new IndexKeyInfo(Arrays.asList(hashesDesc), new CoercionDesc(isCoerceHash, hashPropCoercionTypes),
                Arrays.asList(rangesDesc), new CoercionDesc(isCoerceRange, rangePropCoercionTypes));
    }

    private static IndexNameAndDescPair[] getTableClassNamePairs(EventTableAndNamePair[] pairs) {
        if (pairs == null) {
            return new IndexNameAndDescPair[0];
        }
        IndexNameAndDescPair[] names = new IndexNameAndDescPair[pairs.length];
        for (int i = 0; i < pairs.length; i++) {
            names[i] = new IndexNameAndDescPair(pairs[i].getIndexName(),
                    pairs[i].getEventTable().getClass().getSimpleName());
        }
        return names;
    }

    public static EventTable[] realizeTables(SubordinateQueryIndexDesc[] indexDescriptors, EventType eventType,
            EventTableIndexRepository indexRepository, Iterable<EventBean> contents) {
        EventTable[] tables = new EventTable[indexDescriptors.length];
        for (int i = 0; i < tables.length; i++) {
            SubordinateQueryIndexDesc desc = indexDescriptors[i];
            EventTable table = indexRepository.getIndexByDesc(desc.getIndexMultiKey());
            if (table == null) {
                table = EventTableUtil.buildIndex(0, desc.getQueryPlanIndexItem(), eventType, true,
                        desc.getIndexMultiKey().isUnique(), null);

                // fill table since its new
                EventBean[] events = new EventBean[1];
                for (EventBean prefilledEvent : contents) {
                    events[0] = prefilledEvent;
                    table.add(events);
                }

                indexRepository.addIndex(desc.getIndexMultiKey(), new EventTableIndexRepositoryEntry(null, table));
            }
            tables[i] = table;
        }
        return tables;
    }

    public static void addIndexMetaAndRef(SubordinateQueryIndexDesc[] indexDescs, EventTableIndexMetadata repo,
            String statementName) throws ExprValidationException {
        for (SubordinateQueryIndexDesc desc : indexDescs) {
            if (desc.getIndexName() != null) {
                repo.addIndexReference(desc.getIndexName(), statementName);
            } else {
                repo.addIndex(false, desc.getIndexMultiKey(), null, statementName, false);
                repo.addIndexReference(desc.getIndexMultiKey(), statementName);
            }
        }
    }
}