/// <summary>
        /// The FindIndex
        /// </summary>
        /// <param name="keyNamesAvailable">The key names available.</param>
        /// <param name="rangeNamesAvailable">The range names available.</param>
        /// <param name="indexRepository">The <see cref="EventTableIndexRepository" /></param>
        /// <param name="virtualDataWindow">The <see cref="VirtualDWView" /></param>
        /// <param name="attributes">The <see cref="Attribute" /> array</param>
        /// <returns></returns>
        private static Pair <IndexMultiKey, EventTableAndNamePair> FindIndex(
            ISet <string> keyNamesAvailable,
            ISet <string> rangeNamesAvailable,
            EventTableIndexRepository indexRepository,
            VirtualDWView virtualDataWindow,
            Attribute[] attributes)
        {
            if (virtualDataWindow != null)
            {
                var tablePairNoName = virtualDataWindow.GetFireAndForgetDesc(keyNamesAvailable, rangeNamesAvailable);
                return(new Pair <IndexMultiKey, EventTableAndNamePair>(tablePairNoName.First, new EventTableAndNamePair(tablePairNoName.Second, null)));
            }
            var indexHint = IndexHint.GetIndexHint(attributes);
            var optionalIndexHintInstructions = indexHint != null ? indexHint.InstructionsFireAndForget : null;

            return(indexRepository.FindTable(keyNamesAvailable, rangeNamesAvailable, optionalIndexHintInstructions));
        }
Beispiel #2
0
        public static ICollection <EventBean> Snapshot(
            FilterSpecCompiled optionalFilter,
            Attribute[] annotations,
            VirtualDWView virtualDataWindow,
            EventTableIndexRepository indexRepository,
            bool queryPlanLogging,
            ILog queryPlanLogDestination,
            string objectName,
            AgentInstanceContext agentInstanceContext)
        {
            if (optionalFilter == null || optionalFilter.Parameters.Length == 0)
            {
                if (virtualDataWindow != null)
                {
                    var pair = virtualDataWindow.GetFireAndForgetDesc(Collections.GetEmptySet <string>(), Collections.GetEmptySet <string>());
                    return(virtualDataWindow.GetFireAndForgetData(pair.Second, new object[0], new RangeIndexLookupValue[0], annotations));
                }
                return(null);
            }

            // Determine what straight-equals keys and which ranges are available.
            // Widening/Coercion is part of filter spec compile.
            ISet <string> keysAvailable   = new HashSet <string>();
            ISet <string> rangesAvailable = new HashSet <string>();

            if (optionalFilter.Parameters.Length == 1)
            {
                foreach (FilterSpecParam param in optionalFilter.Parameters[0])
                {
                    if (!(param is FilterSpecParamConstant ||
                          param is FilterSpecParamRange ||
                          param is FilterSpecParamIn))
                    {
                        continue;
                    }

                    if (param.FilterOperator == FilterOperator.EQUAL ||
                        param.FilterOperator == FilterOperator.IS ||
                        param.FilterOperator == FilterOperator.IN_LIST_OF_VALUES)
                    {
                        keysAvailable.Add(param.Lookupable.Expression);
                    }
                    else if (param.FilterOperator.IsRangeOperator() ||
                             param.FilterOperator.IsInvertedRangeOperator() ||
                             param.FilterOperator.IsComparisonOperator())
                    {
                        rangesAvailable.Add(param.Lookupable.Expression);
                    }
                    else if (param.FilterOperator.IsRangeOperator())
                    {
                        rangesAvailable.Add(param.Lookupable.Expression);
                    }
                }
            }

            // Find an index that matches the needs
            Pair <IndexMultiKey, EventTableAndNamePair> tablePair;

            if (virtualDataWindow != null)
            {
                var tablePairNoName = virtualDataWindow.GetFireAndForgetDesc(keysAvailable, rangesAvailable);
                tablePair = new Pair <IndexMultiKey, EventTableAndNamePair>(tablePairNoName.First, new EventTableAndNamePair(tablePairNoName.Second, null));
            }
            else
            {
                var indexHint = IndexHint.GetIndexHint(annotations);
                IList <IndexHintInstruction> optionalIndexHintInstructions = null;
                if (indexHint != null)
                {
                    optionalIndexHintInstructions = indexHint.InstructionsFireAndForget;
                }
                tablePair = indexRepository.FindTable(keysAvailable, rangesAvailable, optionalIndexHintInstructions);
            }

            var hook = QueryPlanIndexHookUtil.GetHook(annotations);

            if (queryPlanLogging && (queryPlanLogDestination.IsInfoEnabled || hook != null))
            {
                var prefix    = "Fire-and-forget from " + objectName + " ";
                var indexName = tablePair != null && tablePair.Second != null ? tablePair.Second.IndexName : null;
                var indexText = indexName != null ? "index " + indexName + " " : "full table scan ";
                indexText += "(snapshot only, for join see separate query plan)";
                if (tablePair == null)
                {
                    queryPlanLogDestination.Info(prefix + indexText);
                }
                else
                {
                    queryPlanLogDestination.Info(prefix + indexText + tablePair.Second.EventTable.ToQueryPlan());
                }

                if (hook != null)
                {
                    hook.FireAndForget(new QueryPlanIndexDescFAF(
                                           new IndexNameAndDescPair[] {
                        new IndexNameAndDescPair(indexName, tablePair != null ?
                                                 tablePair.Second.EventTable.ProviderClass.Name : null)
                    }));
                }
            }

            if (tablePair == null)
            {
                return(null);    // indicates table scan
            }

            // Compile key sets which contain key index lookup values
            var keyIndexProps      = IndexedPropDesc.GetIndexProperties(tablePair.First.HashIndexedProps);
            var hasKeyWithInClause = false;
            var keyValues          = new object[keyIndexProps.Length];

            for (var keyIndex = 0; keyIndex < keyIndexProps.Length; keyIndex++)
            {
                foreach (var param in optionalFilter.Parameters[0])
                {
                    if (param.Lookupable.Expression.Equals(keyIndexProps[keyIndex]))
                    {
                        if (param.FilterOperator == FilterOperator.IN_LIST_OF_VALUES)
                        {
                            var keyValuesList = ((MultiKeyUntyped)param.GetFilterValue(null, agentInstanceContext)).Keys;
                            if (keyValuesList.Length == 0)
                            {
                                continue;
                            }
                            else if (keyValuesList.Length == 1)
                            {
                                keyValues[keyIndex] = keyValuesList[0];
                            }
                            else
                            {
                                keyValues[keyIndex] = keyValuesList;
                                hasKeyWithInClause  = true;
                            }
                        }
                        else
                        {
                            keyValues[keyIndex] = param.GetFilterValue(null, agentInstanceContext);
                        }
                        break;
                    }
                }
            }

            // Analyze ranges - these may include key lookup value (EQUALS semantics)
            var rangeIndexProps = IndexedPropDesc.GetIndexProperties(tablePair.First.RangeIndexedProps);

            RangeIndexLookupValue[] rangeValues;
            if (rangeIndexProps.Length > 0)
            {
                rangeValues = CompileRangeLookupValues(rangeIndexProps, optionalFilter.Parameters[0], agentInstanceContext);
            }
            else
            {
                rangeValues = new RangeIndexLookupValue[0];
            }

            var eventTable    = tablePair.Second.EventTable;
            var indexMultiKey = tablePair.First;

            // table lookup without in-clause
            if (!hasKeyWithInClause)
            {
                return(FafTableLookup(virtualDataWindow, indexMultiKey, eventTable, keyValues, rangeValues, annotations));
            }

            // table lookup with in-clause: determine combinations
            var combinations = new object[keyIndexProps.Length][];

            for (var i = 0; i < keyValues.Length; i++)
            {
                if (keyValues[i] is object[])
                {
                    combinations[i] = (object[])keyValues[i];
                }
                else
                {
                    combinations[i] = new object[] { keyValues[i] };
                }
            }

            // enumerate combinations
            var enumeration = new CombinationEnumeration(combinations);
            var events      = new HashSet <EventBean>();

            for (; enumeration.MoveNext();)
            {
                object[] keys   = enumeration.Current;
                var      result = FafTableLookup(virtualDataWindow, indexMultiKey, eventTable, keys, rangeValues, annotations);
                events.AddAll(result);
            }
            return(events);
        }
        /// <summary>
        /// The snapshot
        /// </summary>
        /// <param name="queryGraph">The <see cref="QueryGraph"/></param>
        /// <param name="attributes">The <see cref="Attribute" /> array</param>
        /// <param name="virtualDataWindow">The <see cref="VirtualDWView"/></param>
        /// <param name="indexRepository">The <see cref="EventTableIndexRepository"/></param>
        /// <param name="queryPlanLogging">The <see cref="bool"/></param>
        /// <param name="queryPlanLogDestination">The <see cref="ILog"/></param>
        /// <param name="objectName">The <see cref="string"/></param>
        /// <param name="agentInstanceContext">The <see cref="AgentInstanceContext"/></param>
        /// <returns>The <see cref="ICollection{EventBean}"/></returns>
        public static ICollection <EventBean> Snapshot(
            QueryGraph queryGraph,
            Attribute[] attributes,
            VirtualDWView virtualDataWindow,
            EventTableIndexRepository indexRepository,
            bool queryPlanLogging,
            ILog queryPlanLogDestination,
            string objectName,
            AgentInstanceContext agentInstanceContext)
        {
            var queryGraphValue = queryGraph == null ? null : queryGraph.GetGraphValue(QueryGraph.SELF_STREAM, 0);

            if (queryGraphValue == null || queryGraphValue.Items.IsEmpty())
            {
                if (virtualDataWindow != null)
                {
                    var pair = virtualDataWindow.GetFireAndForgetDesc(Collections.GetEmptySet <string>(), Collections.GetEmptySet <string>());
                    return(virtualDataWindow.GetFireAndForgetData(pair.Second, new Object[0], new RangeIndexLookupValue[0], attributes));
                }
                return(null);
            }

            // determine custom index
            var customResult = SnapshotCustomIndex(
                queryGraphValue, indexRepository, attributes, agentInstanceContext, queryPlanLogging, queryPlanLogDestination, objectName);

            if (customResult != null)
            {
                return(customResult.Value);
            }

            // determine lookup based on hash-keys and ranges
            var keysAvailable     = queryGraphValue.HashKeyProps;
            var keyNamesAvailable = keysAvailable.Indexed.Count == 0
                ? Collections.GetEmptySet <string>()
                : new HashSet <string>(keysAvailable.Indexed);
            var rangesAvailable     = queryGraphValue.RangeProps;
            var rangeNamesAvailable = rangesAvailable.Indexed.Count == 0
                ? Collections.GetEmptySet <string>()
                : new HashSet <string>(rangesAvailable.Indexed);

            // find index that matches the needs
            var tablePair = FindIndex(keyNamesAvailable, rangeNamesAvailable, indexRepository, virtualDataWindow, attributes);

            // regular index lookup
            if (tablePair != null)
            {
                return(SnapshotIndex(keysAvailable, rangesAvailable, tablePair, virtualDataWindow, attributes, agentInstanceContext, queryPlanLogging, queryPlanLogDestination, objectName));
            }

            // in-keyword lookup
            var inkwResult = SnapshotInKeyword(queryGraphValue, indexRepository, virtualDataWindow, attributes, agentInstanceContext, queryPlanLogging, queryPlanLogDestination, objectName);

            if (inkwResult != null)
            {
                return(inkwResult.Value);
            }

            QueryPlanReportTableScan(attributes, agentInstanceContext, queryPlanLogging, queryPlanLogDestination, objectName);
            return(null);
        }