Ejemplo n.º 1
0
        private static SubordPropRangeKeyForge[] GetRangeFuncsAsSubProp(IList<QueryGraphValueEntryRangeForge> funcs)
        {
            var keys = new SubordPropRangeKeyForge[funcs.Count];
            for (var i = 0; i < funcs.Count; i++) {
                var func = funcs[i];
                keys[i] = new SubordPropRangeKeyForge(func, func.Expressions[0].Forge.EvaluationType);
            }

            return keys;
        }
Ejemplo n.º 2
0
 public SubordSortedTableLookupStrategyFactoryForge(
     bool isNWOnTrigger,
     int numStreamsOuter,
     SubordPropRangeKeyForge rangeKey,
     CoercionDesc coercionDesc)
 {
     this._isNwOnTrigger = isNWOnTrigger;
     this._numStreamsOuter = numStreamsOuter;
     this._rangeKey = rangeKey;
     this._coercionDesc = coercionDesc;
 }
Ejemplo n.º 3
0
        /// <summary>
        ///     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 accessAccessors for both hash and range,
        ///     return the ordered keys and coercion information.
        /// </summary>
        /// <param name="indexMultiKey">index definition</param>
        /// <param name="hashIndexPropsProvided">hash indexable properties</param>
        /// <param name="hashJoinedProps">keys for hash indexable properties</param>
        /// <param name="rangeIndexPropsProvided">btree indexable properties</param>
        /// <param name="rangeJoinedProps">keys for btree indexable properties</param>
        /// <returns>ordered set of key information</returns>
        public static IndexKeyInfo CompileIndexKeyInfo(
            IndexMultiKey indexMultiKey,
            string[] hashIndexPropsProvided,
            SubordPropHashKeyForge[] hashJoinedProps,
            string[] rangeIndexPropsProvided,
            SubordPropRangeKeyForge[] rangeJoinedProps)
        {
            // map the order of indexed columns (key) to the key information available
            var indexedKeyProps = indexMultiKey.HashIndexedProps;
            var isCoerceHash = false;
            var hashesDesc = new SubordPropHashKeyForge[indexedKeyProps.Length];
            var hashPropCoercionTypes = new Type[indexedKeyProps.Length];

            for (var i = 0; i < indexedKeyProps.Length; i++) {
                var indexField = indexedKeyProps[i].IndexPropName;
                var 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].CoercionType;
                var keyForge = hashesDesc[i].HashKey.KeyExpr.Forge;
                if (indexedKeyProps[i].CoercionType.GetBoxedType() != keyForge.EvaluationType.GetBoxedType()) {   // we allow null evaluator
                    isCoerceHash = true;
                }
            }

            // map the order of range columns (range) to the range information available
            indexedKeyProps = indexMultiKey.RangeIndexedProps;
            var rangesDesc = new SubordPropRangeKeyForge[indexedKeyProps.Length];
            var rangePropCoercionTypes = new Type[indexedKeyProps.Length];
            var isCoerceRange = false;
            for (var i = 0; i < indexedKeyProps.Length; i++) {
                var indexField = indexedKeyProps[i].IndexPropName;
                var 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].CoercionType;
                if (indexedKeyProps[i].CoercionType.GetBoxedType() != rangePropCoercionTypes[i].GetBoxedType()) {
                    isCoerceRange = true;
                }
            }

            return new IndexKeyInfo(
                hashesDesc,
                new CoercionDesc(isCoerceHash, hashPropCoercionTypes),
                rangesDesc,
                new CoercionDesc(isCoerceRange, rangePropCoercionTypes));
        }
Ejemplo n.º 4
0
        public static Type GetCoercionTypeRange(
            EventType indexedType,
            string indexedProp,
            SubordPropRangeKeyForge rangeKey)
        {
            var desc = rangeKey.RangeInfo;
            if (desc.Type.IsRange()) {
                var rangeIn = (QueryGraphValueEntryRangeInForge) desc;
                return GetCoercionTypeRangeIn(
                    indexedType.GetPropertyType(indexedProp),
                    rangeIn.ExprStart,
                    rangeIn.ExprEnd);
            }

            var relOp = (QueryGraphValueEntryRangeRelOpForge) desc;
            return GetCoercionType(indexedType.GetPropertyType(indexedProp), relOp.Expression.Forge.EvaluationType);
        }
Ejemplo n.º 5
0
        private static SubordinateQueryPlannerIndexPropDesc GetIndexPropDesc(
            IDictionary<string, SubordPropHashKeyForge> hashProps,
            IDictionary<string, SubordPropRangeKeyForge> rangeProps)
        {
            // hash property names and types
            var hashIndexPropsProvided = new string[hashProps.Count];
            var hashIndexCoercionType = new Type[hashProps.Count];
            var hashJoinedProps = new SubordPropHashKeyForge[hashProps.Count];
            var count = 0;
            foreach (var entry in hashProps) {
                hashIndexPropsProvided[count] = entry.Key;
                hashIndexCoercionType[count] = entry.Value.CoercionType;
                hashJoinedProps[count++] = entry.Value;
            }

            // range property names and types
            var rangeIndexPropsProvided = new string[rangeProps.Count];
            var rangeIndexCoercionType = new Type[rangeProps.Count];
            var rangeJoinedProps = new SubordPropRangeKeyForge[rangeProps.Count];
            count = 0;
            foreach (var entry in rangeProps) {
                rangeIndexPropsProvided[count] = entry.Key;
                rangeIndexCoercionType[count] = entry.Value.CoercionType;
                rangeJoinedProps[count++] = entry.Value;
            }

            // Add all joined fields to an array for sorting
            var listPair = SubordinateQueryPlannerUtil.ToListOfHashedAndBtreeProps(
                hashIndexPropsProvided,
                hashIndexCoercionType,
                rangeIndexPropsProvided,
                rangeIndexCoercionType);
            return new SubordinateQueryPlannerIndexPropDesc(
                hashIndexPropsProvided,
                hashIndexCoercionType,
                rangeIndexPropsProvided,
                rangeIndexCoercionType,
                listPair,
                hashJoinedProps,
                rangeJoinedProps);
        }
Ejemplo n.º 6
0
        public static SubordPropPlan GetJoinProps(
            ExprNode filterExpr,
            int outsideStreamCount,
            EventType[] allStreamTypesZeroIndexed,
            ExcludePlanHint excludePlanHint)
        {
            // No filter expression means full table scan
            if (filterExpr == null) {
                return new SubordPropPlan();
            }

            // analyze query graph
            var queryGraph = new QueryGraphForge(outsideStreamCount + 1, excludePlanHint, true);
            FilterExprAnalyzer.Analyze(filterExpr, queryGraph, false);

            // Build a list of streams and indexes
            var joinProps = new LinkedHashMap<string, SubordPropHashKeyForge>();
            var rangeProps = new LinkedHashMap<string, SubordPropRangeKeyForge>();
            IDictionary<QueryGraphValueEntryCustomKeyForge, QueryGraphValueEntryCustomOperationForge> customIndexOps =
                EmptyDictionary<QueryGraphValueEntryCustomKeyForge, QueryGraphValueEntryCustomOperationForge>.Instance;

            for (var stream = 0; stream < outsideStreamCount; stream++) {
                var lookupStream = stream + 1;

                var queryGraphValue = queryGraph.GetGraphValue(lookupStream, 0);
                var hashKeysAndIndexes = queryGraphValue.HashKeyProps;

                // determine application functions
                foreach (var item in queryGraphValue.Items) {
                    if (item.Entry is QueryGraphValueEntryCustomForge) {
                        if (customIndexOps.IsEmpty()) {
                            customIndexOps =
                                new Dictionary<QueryGraphValueEntryCustomKeyForge,
                                    QueryGraphValueEntryCustomOperationForge>();
                        }

                        var custom = (QueryGraphValueEntryCustomForge) item.Entry;
                        custom.MergeInto(customIndexOps);
                    }
                }

                // handle key-lookups
                var keyPropertiesJoin = hashKeysAndIndexes.Keys;
                var indexPropertiesJoin = hashKeysAndIndexes.Indexed;
                if (!keyPropertiesJoin.IsEmpty()) {
                    if (keyPropertiesJoin.Count != indexPropertiesJoin.Length) {
                        throw new IllegalStateException(
                            "Invalid query key and index property collection for stream " + stream);
                    }

                    for (var i = 0; i < keyPropertiesJoin.Count; i++) {
                        QueryGraphValueEntryHashKeyedForge keyDesc = keyPropertiesJoin[i];
                        var compareNode = keyDesc.KeyExpr;

                        var keyPropType = compareNode.Forge.EvaluationType.GetBoxedType();
                        var indexedPropType = allStreamTypesZeroIndexed[0]
                            .GetPropertyType(indexPropertiesJoin[i])
                            .GetBoxedType();
                        var coercionType = indexedPropType;
                        if (keyPropType != indexedPropType) {
                            coercionType = keyPropType.GetCompareToCoercionType(indexedPropType);
                        }

                        SubordPropHashKeyForge desc;
                        if (keyPropertiesJoin[i] is QueryGraphValueEntryHashKeyedForgeExpr) {
                            var keyExpr = (QueryGraphValueEntryHashKeyedForgeExpr) keyPropertiesJoin[i];
                            var keyStreamNum = keyExpr.IsRequiresKey ? (int?) stream : null;
                            desc = new SubordPropHashKeyForge(keyDesc, keyStreamNum, coercionType);
                        }
                        else {
                            var prop = (QueryGraphValueEntryHashKeyedForgeProp) keyDesc;
                            desc = new SubordPropHashKeyForge(prop, stream, coercionType);
                        }

                        joinProps.Put(indexPropertiesJoin[i], desc);
                    }
                }

                // handle range lookups
                var rangeKeysAndIndexes = queryGraphValue.RangeProps;
                var rangeIndexes = rangeKeysAndIndexes.Indexed;
                var rangeDescs = rangeKeysAndIndexes.Keys;
                if (rangeDescs.IsEmpty()) {
                    continue;
                }

                // get all ranges lookups
                var count = -1;
                foreach (var rangeDesc in rangeDescs) {
                    count++;
                    var rangeIndexProp = rangeIndexes[count];

                    var subqRangeDesc = rangeProps.Get(rangeIndexProp);

                    // other streams may specify the start or end endpoint of a range, therefore this operation can be additive
                    if (subqRangeDesc != null) {
                        if (subqRangeDesc.RangeInfo.Type.IsRange()) {
                            continue;
                        }

                        // see if we can make this additive by using a range
                        var relOpOther = (QueryGraphValueEntryRangeRelOpForge) subqRangeDesc.RangeInfo;
                        var relOpThis = (QueryGraphValueEntryRangeRelOpForge) rangeDesc;

                        var opsDesc = QueryGraphRangeUtil.GetCanConsolidate(relOpThis.Type, relOpOther.Type);
                        if (opsDesc != null) {
                            ExprNode start;
                            ExprNode end;
                            if (!opsDesc.IsReverse) {
                                start = relOpOther.Expression;
                                end = relOpThis.Expression;
                            }
                            else {
                                start = relOpThis.Expression;
                                end = relOpOther.Expression;
                            }

                            var allowRangeReversal = relOpOther.IsBetweenPart && relOpThis.IsBetweenPart;
                            var rangeIn = new QueryGraphValueEntryRangeInForge(
                                opsDesc.Type,
                                start,
                                end,
                                allowRangeReversal);

                            var indexedPropType = allStreamTypesZeroIndexed[0]
                                .GetPropertyType(rangeIndexProp)
                                .GetBoxedType();
                            var coercionType = indexedPropType;
                            var proposedType = CoercionUtil.GetCoercionTypeRangeIn(
                                indexedPropType,
                                rangeIn.ExprStart,
                                rangeIn.ExprEnd);
                            if (proposedType != null && proposedType != indexedPropType) {
                                coercionType = proposedType;
                            }

                            subqRangeDesc = new SubordPropRangeKeyForge(rangeIn, coercionType);
                            rangeProps.Put(rangeIndexProp, subqRangeDesc);
                        }

                        // ignore
                        continue;
                    }

                    // an existing entry has not been found
                    if (rangeDesc.Type.IsRange()) {
                        var rangeIn = (QueryGraphValueEntryRangeInForge) rangeDesc;
                        var indexedPropType =
                            allStreamTypesZeroIndexed[0].GetPropertyType(rangeIndexProp).GetBoxedType();
                        var coercionType = indexedPropType;
                        var proposedType = CoercionUtil.GetCoercionTypeRangeIn(
                            indexedPropType,
                            rangeIn.ExprStart,
                            rangeIn.ExprEnd);
                        if (proposedType != null && proposedType != indexedPropType) {
                            coercionType = proposedType;
                        }

                        subqRangeDesc = new SubordPropRangeKeyForge(rangeDesc, coercionType);
                    }
                    else {
                        var relOp = (QueryGraphValueEntryRangeRelOpForge) rangeDesc;
                        var keyPropType = relOp.Expression.Forge.EvaluationType;
                        var indexedPropType =
                            allStreamTypesZeroIndexed[0].GetPropertyType(rangeIndexProp).GetBoxedType();
                        var coercionType = indexedPropType;
                        if (keyPropType != indexedPropType) {
                            coercionType = keyPropType.GetCompareToCoercionType(indexedPropType);
                        }

                        subqRangeDesc = new SubordPropRangeKeyForge(rangeDesc, coercionType);
                    }

                    rangeProps.Put(rangeIndexProp, subqRangeDesc);
                }
            }

            SubordPropInKeywordSingleIndex inKeywordSingleIdxProp = null;
            SubordPropInKeywordMultiIndex inKeywordMultiIdxProp = null;
            if (joinProps.IsEmpty() && rangeProps.IsEmpty()) {
                for (var stream = 0; stream < outsideStreamCount; stream++) {
                    var lookupStream = stream + 1;
                    var queryGraphValue = queryGraph.GetGraphValue(lookupStream, 0);

                    var inkwSingles = queryGraphValue.InKeywordSingles;
                    if (inkwSingles.Indexed.Length != 0) {
                        ExprNode[] keys = inkwSingles.Key[0].KeyExprs;
                        var key = inkwSingles.Indexed[0];
                        if (inKeywordSingleIdxProp != null) {
                            continue;
                        }

                        var coercionType = keys[0].Forge.EvaluationType; // for in-comparison the same type is required
                        inKeywordSingleIdxProp = new SubordPropInKeywordSingleIndex(key, coercionType, keys);
                    }

                    var inkwMultis = queryGraphValue.InKeywordMulti;
                    if (!inkwMultis.IsEmpty()) {
                        QueryGraphValuePairInKWMultiIdx multi = inkwMultis[0];
                        inKeywordMultiIdxProp = new SubordPropInKeywordMultiIndex(
                            ExprNodeUtilityQuery.GetIdentResolvedPropertyNames(multi.Indexed),
                            multi.Indexed[0].Forge.EvaluationType,
                            multi.Key.KeyExpr);
                    }

                    if (inKeywordSingleIdxProp != null && inKeywordMultiIdxProp != null) {
                        inKeywordMultiIdxProp = null;
                    }
                }
            }

            return new SubordPropPlan(
                joinProps,
                rangeProps,
                inKeywordSingleIdxProp,
                inKeywordMultiIdxProp,
                customIndexOps);
        }