Beispiel #1
0
 public override string ToString()
 {
     return("TableLookupKeyDesc{" +
            "hashes=" + QueryGraphValueEntryHashKeyed.ToQueryPlan(Hashes) +
            ", btree=" + QueryGraphValueEntryRange.ToQueryPlan(Ranges) +
            '}');
 }
Beispiel #2
0
        public static Type GetCoercionTypeRange(EventType indexedType, String indexedProp, SubordPropRangeKey rangeKey)
        {
            QueryGraphValueEntryRange desc = rangeKey.RangeInfo;

            if (desc.RangeType.IsRange())
            {
                var rangeIn = (QueryGraphValueEntryRangeIn)desc;
                return(GetCoercionTypeRangeIn(indexedType.GetPropertyType(indexedProp), rangeIn.ExprStart, rangeIn.ExprEnd));
            }

            var relOp = (QueryGraphValueEntryRangeRelOp)desc;

            return(GetCoercionType(indexedType.GetPropertyType(indexedProp), relOp.Expression.ExprEvaluator.ReturnType));
        }
Beispiel #3
0
        public static CoercionDesc GetCoercionTypesRange(EventType[] typesPerStream, int indexedStream, IList <string> indexedProp, IList <QueryGraphValueEntryRange> rangeEntries)
        {
            if (rangeEntries.IsEmpty())
            {
                return(new CoercionDesc(false, NULL_ARRAY));
            }

            var  coercionTypes = new Type[rangeEntries.Count];
            bool mustCoerce    = false;

            for (int i = 0; i < rangeEntries.Count; i++)
            {
                QueryGraphValueEntryRange entry = rangeEntries[i];

                String indexed       = indexedProp[i];
                Type   valuePropType = typesPerStream[indexedStream].GetPropertyType(indexed).GetBoxedType();
                Type   coercionType;

                if (entry.RangeType.IsRange())
                {
                    var rangeIn = (QueryGraphValueEntryRangeIn)entry;
                    coercionType = GetCoercionTypeRangeIn(valuePropType, rangeIn.ExprStart, rangeIn.ExprEnd);
                }
                else
                {
                    var relOp = (QueryGraphValueEntryRangeRelOp)entry;
                    coercionType = GetCoercionType(valuePropType, relOp.Expression.ExprEvaluator.ReturnType);
                }

                if (coercionType == null)
                {
                    coercionTypes[i] = valuePropType;
                }
                else
                {
                    mustCoerce       = true;
                    coercionTypes[i] = coercionType;
                }
            }

            return(new CoercionDesc(mustCoerce, coercionTypes));
        }
Beispiel #4
0
        public static CoercionDesc GetCoercionTypesRange(EventType viewableEventType, IDictionary <String, SubordPropRangeKey> rangeProps, EventType[] typesPerStream)
        {
            if (rangeProps.IsEmpty())
            {
                return(new CoercionDesc(false, NULL_ARRAY));
            }

            var  coercionTypes = new Type[rangeProps.Count];
            bool mustCoerce    = false;
            int  count         = 0;

            foreach (KeyValuePair <String, SubordPropRangeKey> entry in rangeProps)
            {
                SubordPropRangeKey        subQRange = entry.Value;
                QueryGraphValueEntryRange rangeDesc = entry.Value.RangeInfo;

                Type valuePropType = viewableEventType.GetPropertyType(entry.Key).GetBoxedType();
                Type coercionType;

                if (rangeDesc.RangeType.IsRange())
                {
                    var rangeIn = (QueryGraphValueEntryRangeIn)rangeDesc;
                    coercionType = GetCoercionTypeRangeIn(valuePropType, rangeIn.ExprStart, rangeIn.ExprEnd);
                }
                else
                {
                    var relOp = (QueryGraphValueEntryRangeRelOp)rangeDesc;
                    coercionType = GetCoercionType(valuePropType, relOp.Expression.ExprEvaluator.ReturnType);
                }

                if (coercionType == null)
                {
                    coercionTypes[count++] = valuePropType;
                }
                else
                {
                    mustCoerce             = true;
                    coercionTypes[count++] = coercionType;
                }
            }
            return(new CoercionDesc(mustCoerce, coercionTypes));
        }
 /// <summary>
 /// Ctor.
 /// </summary>
 /// <param name="lookupStream">stream that generates event to look up for</param>
 /// <param name="indexedStream">stream to index table lookup</param>
 /// <param name="indexNum">index number for the table containing the full unindexed contents</param>
 /// <param name="rangeKeyPair">The range key pair.</param>
 public SortedTableLookupPlan(int lookupStream, int indexedStream, TableLookupIndexReqKey indexNum, QueryGraphValueEntryRange rangeKeyPair)
     : base(lookupStream, indexedStream, new TableLookupIndexReqKey[] { indexNum })
 {
     _rangeKeyPair = rangeKeyPair;
     _lookupStream = lookupStream;
 }
Beispiel #6
0
        /// <summary>
        /// Create the table lookup plan for a from-stream to look up in an indexed stream
        /// using the columns supplied in the query graph and looking at the actual indexes available
        /// and their index number.
        /// </summary>
        /// <param name="queryGraph">contains properties joining the 2 streams</param>
        /// <param name="currentLookupStream">stream to use key values from</param>
        /// <param name="indexedStream">stream to look up in</param>
        /// <param name="indexSpecs">index specification defining indexes to be created for stream</param>
        /// <param name="typesPerStream">event types for each stream</param>
        /// <returns>plan for performing a lookup in a given table using one of the indexes supplied</returns>
        public static TableLookupPlan CreateLookupPlan(QueryGraph queryGraph, int currentLookupStream, int indexedStream,
                                                       QueryPlanIndex indexSpecs, EventType[] typesPerStream,
                                                       TableMetadata indexedStreamTableMeta)
        {
            var queryGraphValue = queryGraph.GetGraphValue(currentLookupStream, indexedStream);
            var hashKeyProps    = queryGraphValue.HashKeyProps;
            var hashPropsKeys   = hashKeyProps.Keys;
            var hashIndexProps  = hashKeyProps.Indexed.ToArray();

            var rangeProps      = queryGraphValue.RangeProps;
            var rangePropsKeys  = rangeProps.Keys;
            var rangeIndexProps = rangeProps.Indexed.ToArray();

            var pairIndexHashRewrite = indexSpecs.GetIndexNum(hashIndexProps, rangeIndexProps);
            var indexNum             = pairIndexHashRewrite == null ? null : pairIndexHashRewrite.First;

            // handle index redirection towards unique index
            if (pairIndexHashRewrite != null && pairIndexHashRewrite.Second != null)
            {
                var indexes           = pairIndexHashRewrite.Second;
                var newHashIndexProps = new string[indexes.Length];
                IList <QueryGraphValueEntryHashKeyed> newHashKeys = new List <QueryGraphValueEntryHashKeyed>();
                for (var i = 0; i < indexes.Length; i++)
                {
                    newHashIndexProps[i] = hashIndexProps[indexes[i]];
                    newHashKeys.Add(hashPropsKeys[indexes[i]]);
                }
                hashIndexProps  = newHashIndexProps;
                hashPropsKeys   = newHashKeys;
                rangeIndexProps = new string[0];
                rangePropsKeys  = Collections.GetEmptyList <QueryGraphValueEntryRange>();
            }

            // no direct hash or range lookups
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0)
            {
                // handle single-direction 'in' keyword
                var singles = queryGraphValue.InKeywordSingles;
                if (!singles.Key.IsEmpty())
                {
                    QueryGraphValueEntryInKeywordSingleIdx single = null;
                    indexNum = null;
                    if (indexedStreamTableMeta != null)
                    {
                        var indexes = singles.Indexed;
                        var count   = 0;
                        foreach (var index in indexes)
                        {
                            Pair <IndexMultiKey, EventTableIndexEntryBase> indexPairFound =
                                EventTableIndexUtil.FindIndexBestAvailable(
                                    indexedStreamTableMeta.EventTableIndexMetadataRepo.Indexes,
                                    Collections.SingletonSet(index),
                                    Collections.GetEmptySet <string>(), null);
                            if (indexPairFound != null)
                            {
                                indexNum = new TableLookupIndexReqKey(indexPairFound.Second.OptionalIndexName, indexedStreamTableMeta.TableName);
                                single   = singles.Key[count];
                            }
                            count++;
                        }
                    }
                    else
                    {
                        single = singles.Key[0];
                        var pairIndex = indexSpecs.GetIndexNum(new string[] { singles.Indexed[0] }, null);
                        indexNum = pairIndex.First;
                    }

                    if (indexNum != null)
                    {
                        return(new InKeywordTableLookupPlanSingleIdx(currentLookupStream, indexedStream, indexNum, single.KeyExprs));
                    }
                }

                // handle multi-direction 'in' keyword
                var multis = queryGraphValue.InKeywordMulti;
                if (!multis.IsEmpty())
                {
                    if (indexedStreamTableMeta != null)
                    {
                        return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                    }
                    QueryGraphValuePairInKWMultiIdx multi = multis[0];
                    var indexNameArray = new TableLookupIndexReqKey[multi.Indexed.Length];
                    var foundAll       = true;
                    for (var i = 0; i < multi.Indexed.Length; i++)
                    {
                        var identNode = (ExprIdentNode)multi.Indexed[i];
                        var pairIndex = indexSpecs.GetIndexNum(new string[] { identNode.ResolvedPropertyName }, null);
                        if (pairIndex == null)
                        {
                            foundAll = false;
                        }
                        else
                        {
                            indexNameArray[i] = pairIndex.First;
                        }
                    }
                    if (foundAll)
                    {
                        return(new InKeywordTableLookupPlanMultiIdx(currentLookupStream, indexedStream, indexNameArray, multi.Key.KeyExpr));
                    }
                }

                // We don't use a keyed index but use the full stream set as the stream does not have any indexes

                // If no such full set index exists yet, add to specs
                if (indexedStreamTableMeta != null)
                {
                    return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                }
                if (indexNum == null)
                {
                    indexNum = new TableLookupIndexReqKey(indexSpecs.AddIndex(null, null));
                }
                return(new FullTableScanLookupPlan(currentLookupStream, indexedStream, indexNum));
            }

            if (indexNum == null)
            {
                throw new IllegalStateException("Failed to query plan as index for " + hashIndexProps.Render() + " and " + rangeIndexProps.Render() + " in the index specification");
            }

            if (indexedStreamTableMeta != null)
            {
                var indexPairFound = EventTableIndexUtil.FindIndexBestAvailable(indexedStreamTableMeta.EventTableIndexMetadataRepo.Indexes, ToSet(hashIndexProps), ToSet(rangeIndexProps), null);
                if (indexPairFound != null)
                {
                    var indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(indexPairFound.First, hashIndexProps, GetHashKeyFuncsAsSubProp(hashPropsKeys), rangeIndexProps, GetRangeFuncsAsSubProp(rangePropsKeys));
                    if (indexKeyInfo.OrderedKeyCoercionTypes.IsCoerce || indexKeyInfo.OrderedRangeCoercionTypes.IsCoerce)
                    {
                        return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                    }
                    hashPropsKeys   = ToHashKeyFuncs(indexKeyInfo.OrderedHashDesc);
                    hashIndexProps  = IndexedPropDesc.GetIndexProperties(indexPairFound.First.HashIndexedProps);
                    rangePropsKeys  = ToRangeKeyFuncs(indexKeyInfo.OrderedRangeDesc);
                    rangeIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.RangeIndexedProps);
                    indexNum        = new TableLookupIndexReqKey(indexPairFound.Second.OptionalIndexName, indexedStreamTableMeta.TableName);
                    // the plan will be created below
                    if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0)
                    {
                        return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                    }
                }
                else
                {
                    return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                }
            }

            // straight keyed-index lookup
            if (hashIndexProps.Length > 0 && rangeIndexProps.Length == 0)
            {
                TableLookupPlan tableLookupPlan;
                if (hashPropsKeys.Count == 1)
                {
                    tableLookupPlan = new IndexedTableLookupPlanSingle(currentLookupStream, indexedStream, indexNum, hashPropsKeys[0]);
                }
                else
                {
                    tableLookupPlan = new IndexedTableLookupPlanMulti(currentLookupStream, indexedStream, indexNum, hashPropsKeys);
                }

                // Determine coercion required
                var coercionTypes = CoercionUtil.GetCoercionTypesHash(typesPerStream, currentLookupStream, indexedStream, hashPropsKeys, hashIndexProps);
                if (coercionTypes.IsCoerce)
                {
                    // check if there already are coercion types for this index
                    var existCoercionTypes = indexSpecs.GetCoercionTypes(hashIndexProps);
                    if (existCoercionTypes != null)
                    {
                        for (var i = 0; i < existCoercionTypes.Length; i++)
                        {
                            coercionTypes.CoercionTypes[i] = TypeHelper.GetCompareToCoercionType(existCoercionTypes[i], coercionTypes.CoercionTypes[i]);
                        }
                    }
                    indexSpecs.SetCoercionTypes(hashIndexProps, coercionTypes.CoercionTypes);
                }

                return(tableLookupPlan);
            }

            // sorted index lookup
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 1)
            {
                QueryGraphValueEntryRange range = rangePropsKeys[0];
                return(new SortedTableLookupPlan(currentLookupStream, indexedStream, indexNum, range));
            }
            // composite range and index lookup
            else
            {
                return(new CompositeTableLookupPlan(currentLookupStream, indexedStream, indexNum, hashPropsKeys, rangePropsKeys));
            }
        }