public override IExpression CorrectTerm(TermExpression te)
        {
            if (te == null)
            {
                throw new ArgumentNullException("te");
            }

            if (!te.ColumnName.Equals("*"))
            {
                string value = te.Value.ToString();
                if (value.Equals("today", StringComparison.OrdinalIgnoreCase))
                {
                    return(new TermExpression(te.ColumnName, te.Operator, DateTime.Today.ToUniversalTime()));
                }
                else if (value.StartsWith("today-", StringComparison.OrdinalIgnoreCase))
                {
                    int relativeDays = 0;
                    if (int.TryParse(value.Substring(6), out relativeDays))
                    {
                        return(new TermExpression(te.ColumnName, te.Operator, DateTime.Today.AddDays(-relativeDays).ToUniversalTime()));
                    }
                }
            }

            return(null);
        }
 public StringEvaluator(Func <T, string> getter, TermExpression term, StringComparison stringComparison)
 {
     _getter           = getter;
     _value            = term.Value;
     _evaluateSet      = Comparer(term);
     _stringComparison = stringComparison;
 }
Exemple #3
0
        private static void GetAllTerms(IExpression expression, string columnName, List <TermExpression> result)
        {
            if (expression is AllExceptColumnsTermExpression)
            {
                AllExceptColumnsTermExpression te = (AllExceptColumnsTermExpression)expression;
                if (!te.RestrictedColumns.Contains(columnName))
                {
                    result.Add(te);
                }
            }
            else if (expression is TermExpression)
            {
                TermExpression te = (TermExpression)expression;

                if (String.IsNullOrEmpty(columnName) || te.ColumnName.Equals("*") || String.Equals(columnName, te.ColumnName, StringComparison.OrdinalIgnoreCase))
                {
                    result.Add(te);
                }
            }

            foreach (IExpression child in expression.Children())
            {
                GetAllTerms(child, columnName, result);
            }
        }
Exemple #4
0
        public DataBlockResult Compute(Partition p)
        {
            if (p == null)
            {
                throw new ArgumentNullException("p");
            }
            DataBlockResult result = new DataBlockResult(this);

            // Find matches for the remaining query
            ShortSet baseQueryMatches = new ShortSet(p.Count);

            this.Where.TryEvaluate(p, baseQueryMatches, result.Details);

            // Find and count matches per column for the term in the outer query
            List <Tuple <string, int> > matchCountPerColumn = new List <Tuple <string, int> >();

            if (baseQueryMatches.Count() > 0)
            {
                TermExpression bareTerm             = new TermExpression(this.Term);
                ShortSet       termMatchesForColumn = new ShortSet(p.Count);

                bool             succeeded        = false;
                ExecutionDetails perColumnDetails = new ExecutionDetails();

                foreach (IColumn <object> column in p.Columns.Values)
                {
                    termMatchesForColumn.Clear();

                    perColumnDetails.Succeeded = true;
                    column.TryWhere(Operator.Matches, this.Term, termMatchesForColumn, perColumnDetails);
                    succeeded |= perColumnDetails.Succeeded;

                    termMatchesForColumn.And(baseQueryMatches);

                    ushort matchCount = termMatchesForColumn.Count();
                    if (matchCount > 0)
                    {
                        matchCountPerColumn.Add(new Tuple <string, int>(column.Name, (int)matchCount));
                    }
                }

                // Sort results by count of matches descending
                matchCountPerColumn.Sort((left, right) => right.Item2.CompareTo(left.Item2));
            }

            // Copy to a DataBlock and return it
            int       index = 0;
            DataBlock block = new DataBlock(new string[] { "ColumnName", "Count" }, matchCountPerColumn.Count);

            foreach (var column in matchCountPerColumn)
            {
                block[index, 0] = column.Item1;
                block[index, 1] = column.Item2;
                index++;
            }

            result.Values = block;
            result.Total  = baseQueryMatches.Count();
            return(result);
        }
        private static void AddTopColumnValues(IntelliSenseResult result, TermExpression lastTerm, IntelliSenseGuidance guidance, List <IntelliSenseItem> suggestions, Table singleTable, ColumnDetails singleColumn)
        {
            string completeQuery = GetCompleteQueryPrefix(result);

            // Recommend the top ten values in the column with the prefix typed so far
            DistinctResult topValues = singleTable.Query(new DistinctQueryTop(singleColumn.Name, lastTerm.Value.ToString(), completeQuery, 10));
            int            total     = (int)topValues.Total;

            if (topValues.Total == 0)
            {
                return;
            }

            // Walk values in order for ==, :, ::, backwards with inverse percentages for !=
            bool isNotEquals = lastTerm.Operator == Operator.NotEquals;
            int  start       = isNotEquals ? topValues.Values.RowCount - 1 : 0;
            int  end         = isNotEquals ? -1 : topValues.Values.RowCount;
            int  step        = isNotEquals ? -1 : 1;

            for (int i = start; i != end; i += step)
            {
                string value         = topValues.Values[i, 0].ToString();
                int    countForValue = (int)topValues.Values[i, 1];
                if (isNotEquals)
                {
                    countForValue = (int)topValues.Total - countForValue;
                }

                if ((countForValue > 1 || total <= 10) && value.StartsWith(guidance.Value, StringComparison.OrdinalIgnoreCase) && value.Length < 100)
                {
                    suggestions.Add(new IntelliSenseItem(QueryTokenCategory.Value, QueryParser.WrapValue(topValues.Values[i, 0]), countForValue, topValues.Total));
                }
            }
        }
        public override IExpression CorrectTerm(TermExpression te)
        {
            // If we couldn't get the People table, don't do anything
            if (this.People == null)
            {
                return(null);
            }

            // For a specific column, a string value, and an operator safe to correct with 'original OR correction', consider alias correction
            if (!te.ColumnName.Equals("*") && te.Value.BestType().Equals(typeof(string)) && te.Operator.IsOrCorrectableOperator())
            {
                // Query for aliases equal to this value
                string value = te.Value.ToString();

                SelectQuery q = new SelectQuery();
                q.Columns = new string[] { "Display Name" };
                q.Where   = new TermExpression("Alias", Operator.Equals, value);
                q.Count   = 1;

                SelectResult r = this.People.Query(q);

                // If one is found, return the original value or the alias
                if (r.Total > 0)
                {
                    return(new OrExpression(te, new TermExpression(te.ColumnName, te.Operator, r.Values[0, 0])));
                }
            }

            return(null);
        }
        private Action <ICollection <T>, BitArray> Comparer(TermExpression term)
        {
            switch (term.Operator)
            {
            case CompareOperator.Equals:
                return(EvaluateEquals);

            case CompareOperator.NotEquals:
                return(EvaluateNotEquals);

            case CompareOperator.LessThan:
                return(EvaluateLessThan);

            case CompareOperator.LessThanOrEquals:
                return(EvaluateLessThanOrEquals);

            case CompareOperator.GreaterThan:
                return(EvaluateGreaterThan);

            case CompareOperator.GreaterThanOrEquals:
                return(EvaluateGreaterThanOrEquals);

            default:
                throw new QueryParseException($"{term} does not support operator {term.Operator}");
            }
        }
Exemple #8
0
        public static IExpressionEvaluator <Result> ResultEvaluator(TermExpression term)
        {
            string propertyNameLower = term.PropertyName.ToLowerInvariant();

            switch (propertyNameLower)
            {
            case "baselinestate":
                return(new EnumEvaluator <Result, BaselineState>(r => r.BaselineState, term));

            case "correlationguid":
                return(new StringEvaluator <Result>(r => r.CorrelationGuid, term, StringComparison.OrdinalIgnoreCase));

            case "guid":
                return(new StringEvaluator <Result>(r => r.Guid, term, StringComparison.OrdinalIgnoreCase));

            case "hostedvieweruri":
                return(new StringEvaluator <Result>(r => r.HostedViewerUri?.ToString(), term, StringComparison.OrdinalIgnoreCase));

            case "kind":
                return(new EnumEvaluator <Result, ResultKind>(r => r.Kind, term));

            case "level":
                return(new EnumEvaluator <Result, FailureLevel>(r => r.Level, term));

            case "message.text":
                return(new StringEvaluator <Result>(r => r.Message?.Text, term, StringComparison.OrdinalIgnoreCase));

            case "occurrencecount":
                return(new LongEvaluator <Result>(r => r.OccurrenceCount, term));

            case "rank":
                return(new DoubleEvaluator <Result>(r => r.Rank, term));

            case "ruleid":
                return(new StringEvaluator <Result>(r => r.GetRule(r.Run).Id, term, StringComparison.OrdinalIgnoreCase));

            case "uri":
                // Ensure the Run is provided, to look up Uri from Run.Artifacts when needed.
                // Uri : "/Core/" will match all Results with any Uri which contains "/Core/"
                return(new SetEvaluator <Result, string>(r =>
                {
                    r.EnsureRunProvided();
                    return r.Locations?.Select(l => l?.PhysicalLocation?.ArtifactLocation.Resolve(r.Run)?.Uri?.ToString() ?? "");
                }, term));

            default:
                if (propertyNameLower.StartsWith(PropertyBagPropertyEvaluator.ResultPropertyPrefix) ||
                    propertyNameLower.StartsWith(PropertyBagPropertyEvaluator.RulePropertyPrefix))
                {
                    return(new PropertyBagPropertyEvaluator(term));
                }

                throw new QueryParseException(
                          string.Format(
                              CultureInfo.CurrentCulture,
                              SdkResources.ErrorInvalidQueryPropertyName,
                              term.PropertyName));
            }
        }
Exemple #9
0
        /// <summary>
        ///  Build a SetEvaluator given a method to get an IEnumerable&lt;U&gt; of a primitive type
        ///  and the term showing the operator and value to compare against.
        /// </summary>
        /// <param name="getter">Getter to return a set of U given a T</param>
        /// <param name="term">TermExpression for how to match each T</param>
        public SetEvaluator(Func <T, IEnumerable <U> > getter, TermExpression term)
        {
            _getter = getter;

            object innerEvaluator = EvaluatorFactory.BuildPrimitiveEvaluator(typeof(U), term);

            _innerEvaluator = (IExpressionEvaluator <U>)innerEvaluator;
        }
        public void PropertyBagPropertyEvaluator_RejectsPropertyNameWithInvalidPrefix()
        {
            var expression = new TermExpression(propertyName: "invalid.prefix", op: CompareOperator.Equals, value: string.Empty);

            Action action = () => new PropertyBagPropertyEvaluator(expression);

            action.Should().Throw <ArgumentException>();
        }
        private static void AddValueDistribution(IntelliSenseResult result, TermExpression lastTerm, IntelliSenseGuidance guidance, List <IntelliSenseItem> suggestions, Table singleTable, ColumnDetails singleColumn)
        {
            string completeQuery = GetCompleteQueryPrefix(result);

            bool inclusive = (lastTerm.Operator == Operator.LessThanOrEqual || lastTerm.Operator == Operator.GreaterThan);
            bool reverse   = (lastTerm.Operator == Operator.GreaterThan || lastTerm.Operator == Operator.GreaterThanOrEqual);

            // Recommend the top ten values in the column with the prefix typed so far
            DataBlockResult distribution = singleTable.Query(new DistributionQuery(singleColumn.Name, completeQuery, inclusive));

            if (distribution.Total == 0 || distribution.Details.Succeeded == false)
            {
                return;
            }

            int countSoFar;

            if (reverse)
            {
                countSoFar = (int)distribution.Values[distribution.Values.RowCount - 1, 1];

                for (int i = distribution.Values.RowCount - 2; i >= 0; --i)
                {
                    string value         = distribution.Values[i, 0].ToString();
                    double frequency     = (double)countSoFar / (double)(distribution.Total);
                    int    countForRange = (int)distribution.Values[i, 1];

                    if ((distribution.Values.RowCount == 2 || (int)distribution.Values[i + 1, 1] > 0) && value.StartsWith(guidance.Value, StringComparison.OrdinalIgnoreCase))
                    {
                        suggestions.Add(new IntelliSenseItem(QueryTokenCategory.Value, QueryParser.WrapValue(distribution.Values[i, 0]), countSoFar, distribution.Total));
                    }

                    countSoFar += countForRange;
                }
            }
            else
            {
                countSoFar = 0;

                for (int i = 0; i < distribution.Values.RowCount - 1; ++i)
                {
                    string value         = distribution.Values[i, 0].ToString();
                    int    countForRange = (int)distribution.Values[i, 1];
                    countSoFar += countForRange;

                    double frequency = (double)countSoFar / (double)(distribution.Total);

                    if ((distribution.Values.RowCount == 2 || countForRange > 0) && value.StartsWith(guidance.Value, StringComparison.OrdinalIgnoreCase))
                    {
                        suggestions.Add(new IntelliSenseItem(QueryTokenCategory.Value, QueryParser.WrapValue(distribution.Values[i, 0]), countSoFar, distribution.Total));
                    }
                }
            }
        }
        public DoubleEvaluator(Func <T, double> getter, TermExpression term)
        {
            _getter = getter;

            if (!double.TryParse(term.Value, out double parsedValue))
            {
                throw new QueryParseException($"{term} value {term.Value} was not a valid floating point number.");
            }
            _value = parsedValue;

            _evaluateSet = Comparer(term);
        }
        public EnumEvaluator(Func <T, EnumType> getter, TermExpression term)
        {
            _getter = getter;

            if (!Enum.TryParse <EnumType>(term.Value, out EnumType parsedValue))
            {
                throw new QueryParseException($"{term} value {term.Value} was not a valid {typeof(EnumType).Name}.");
            }
            _value = parsedValue;

            _evaluateSet = Comparer(term);
        }
        public LongEvaluator(Func <T, long> getter, TermExpression term)
        {
            _getter = getter;

            if (!long.TryParse(term.Value, out long parsedValue))
            {
                throw new QueryParseException($"{term} value {term.Value} was not a valid number.");
            }
            Value = parsedValue;

            _evaluateSet = Comparer(term);
        }
Exemple #15
0
        public override IExpression CorrectTerm(TermExpression te)
        {
            string value = te.Value.ToString();

            if (value.Equals("me", StringComparison.OrdinalIgnoreCase) && te.Operator.IsOrCorrectableOperator())
            {
                // Correct 'me' to the current user alias, if seen
                return(new OrExpression(te, new TermExpression(te.ColumnName, te.Operator, this.UserAlias)));
            }

            return(null);
        }
        private Action <ICollection <T>, BitArray> Comparer(TermExpression term)
        {
            switch (term.Operator)
            {
            case CompareOperator.Equals:
                return(EvaluateEquals);

            case CompareOperator.NotEquals:
                return(EvaluateNotEquals);

            default:
                throw new QueryParseException($"In {term}, {term.PropertyName} only supports equals and not equals, not operator {term.Operator}");
            }
        }
        /// <summary>
        ///  BuildPrimitiveEvaluator will build an IExpressionEvaluator for supported primitive
        ///  types, set up to work directly on an array of primitives. you can use BuildPrimitiveEvaluator(typeof(int),
        /// </summary>
        /// <example>
        ///  TermExpression term = ExpressionParser.Parse("value > 5");
        ///  IExpressionEvaluator&lt;int&gt; evaluator = BuildPrimitiveEvaluator(typeof(int), term);
        ///
        ///  int[] set;
        /// BitArray matches = new BitArray(set.Length);
        ///  evaluator.Evaluate(set, matches);
        /// </example>
        /// <param name="fieldType">Primitive type of array to build evaluator for</param>
        /// <param name="term">Query term with comparison and constant to evaluate against array</param>
        /// <returns>IExpressionEvaluator for appropriate type</returns>
        public static object BuildPrimitiveEvaluator(Type fieldType, TermExpression term)
        {
            if (fieldType == typeof(bool))
            {
                return(new BoolEvaluator <bool>(value => value, term));
            }
            else if (fieldType == typeof(double))
            {
                return(new DoubleEvaluator <double>(value => value, term));
            }
            else if (fieldType == typeof(float))
            {
                return(new DoubleEvaluator <float>(value => (double)value, term));
            }
            else if (fieldType == typeof(long))
            {
                return(new LongEvaluator <long>(value => value, term));
            }
            else if (fieldType == typeof(int))
            {
                return(new LongEvaluator <int>(value => (long)value, term));
            }
            else if (fieldType == typeof(uint))
            {
                return(new LongEvaluator <uint>(value => (long)value, term));
            }
            else if (fieldType == typeof(short))
            {
                return(new LongEvaluator <short>(value => (long)value, term));
            }
            else if (fieldType == typeof(ushort))
            {
                return(new LongEvaluator <ushort>(value => (long)value, term));
            }
            else if (fieldType == typeof(byte))
            {
                return(new LongEvaluator <byte>(value => (long)value, term));
            }
            else if (fieldType == typeof(sbyte))
            {
                return(new LongEvaluator <sbyte>(value => (long)value, term));
            }
            else if (fieldType == typeof(string))
            {
                // Default StringComparison only
                return(new StringEvaluator <string>(value => value, term, StringComparison.OrdinalIgnoreCase));
            }

            throw new NotImplementedException($"BuildPrimitiveEvaluator not implemented for type {fieldType.FullName}.");
        }
        public static IExpressionEvaluator <Result> ResultEvaluator(TermExpression term)
        {
            switch (term.PropertyName.ToLowerInvariant())
            {
            case "baselinestate":
                return(new EnumEvaluator <Result, BaselineState>(r => r.BaselineState, term));

            case "correlationguid":
                return(new StringEvaluator <Result>(r => r.CorrelationGuid, term, StringComparison.OrdinalIgnoreCase));

            case "guid":
                return(new StringEvaluator <Result>(r => r.Guid, term, StringComparison.OrdinalIgnoreCase));

            case "hostedvieweruri":
                return(new StringEvaluator <Result>(r => r.HostedViewerUri?.ToString(), term, StringComparison.OrdinalIgnoreCase));

            case "kind":
                return(new EnumEvaluator <Result, ResultKind>(r => r.Kind, term));

            case "level":
                return(new EnumEvaluator <Result, FailureLevel>(r => r.Level, term));

            case "message.text":
                return(new StringEvaluator <Result>(r => r.Message?.Text, term, StringComparison.OrdinalIgnoreCase));

            case "occurrencecount":
                return(new LongEvaluator <Result>(r => r.OccurrenceCount, term));

            case "rank":
                return(new DoubleEvaluator <Result>(r => r.Rank, term));

            case "ruleid":
                return(new StringEvaluator <Result>(r => r.GetRule(r.Run).Id, term, StringComparison.OrdinalIgnoreCase));

            case "uri":
                // Ensure the Run is provided, to look up Uri from Run.Artifacts when needed.
                // Uri : "/Core/" will match all Results with any Uri which contains "/Core/"
                return(new SetEvaluator <Result, string>(r =>
                {
                    r.EnsureRunProvided();
                    return r.Locations?.Select(l => l?.PhysicalLocation?.ArtifactLocation.Resolve(r.Run)?.Uri?.ToString() ?? "");
                }, term));

            default:
                throw new QueryParseException($"Property Name {term.PropertyName} unrecognized. Known Names: baselineState, correlationGuid, guid, hostedViewerUri, kind, level, message.text, occurrenceCount, rank, ruleId");
            }
        }
        public override IExpression CorrectTerm(TermExpression te)
        {
            if (te == null)
            {
                throw new ArgumentNullException("te");
            }

            string fullColumnName;

            if (_columnNameMappings.TryGetValue(te.ColumnName, out fullColumnName))
            {
                // NOTE: We change the TermExpression directly rather than replacing it
                te.ColumnName = fullColumnName;
            }

            return(null);
        }
Exemple #20
0
        public override IExpression CorrectTerm(TermExpression te)
        {
            if (te == null)
            {
                throw new ArgumentNullException("te");
            }

            // Look for a join term in the query
            string value = te.Value.ToString();

            if (value.StartsWith("#Q"))
            {
                Regex referenceExpression = new Regex(@"#Q(?<number>\d+)\[(?<columnName>[^\]]+)\]");
                Match m = referenceExpression.Match(value);
                if (m.Success)
                {
                    int    referencedQuery  = int.Parse(m.Groups["number"].Value);
                    string referencedColumn = m.Groups["columnName"].Value;

                    // Get the referenced query and recursively Join it, if required [1-based]
                    SelectQuery joinQuery = this.Queries[referencedQuery - 1];
                    joinQuery.Correct(this.NestedCorrector);
                    joinQuery.Correct(this);

                    // Ask for the Join column and maximum number of values
                    joinQuery.Columns = new string[] { referencedColumn };
                    joinQuery.Count   = ushort.MaxValue;

                    // Run the query
                    Table        t      = this.DB[joinQuery.TableName];
                    SelectResult result = t.Query(joinQuery);

                    if (result.Total == 0)
                    {
                        return(new TermExpression(te.ColumnName, te.Operator, String.Empty));
                    }
                    else
                    {
                        return(new TermInExpression(te.ColumnName, te.Operator, result.Values.GetColumn(0)));
                    }
                }
            }

            return(null);
        }
Exemple #21
0
        public override IExpression CorrectTerm(TermExpression te)
        {
            if (te == null)
            {
                throw new ArgumentNullException("te");
            }

            if (te.ColumnName.Equals("*"))
            {
                return(new AllExceptColumnsTermExpression(_restrictedColumns, te));
            }

            if (_restrictedColumns.Contains(te.ColumnName))
            {
                throw new ArribaColumnAccessDeniedException(te.ColumnName);
            }

            return(null);
        }
Exemple #22
0
        private IExpression NextTerm(IXTable source, XDatabaseContext context)
        {
            IExpression term;
            bool        negate = false;

            // Look for NOT
            if (_scanner.Current.Value.TryParseNot())
            {
                _scanner.Next();
                negate = true;
            }

            // Look for nested subexpression
            if (_scanner.Current.Type == TokenType.OpenParen)
            {
                // Consume the open paren
                _scanner.Next();

                term = NextExpression(source, context);

                // Consume the close paren (and tolerate it missing - partially typed queries)
                if (_scanner.Current.Type == TokenType.CloseParen)
                {
                    _scanner.Next();
                }
            }
            else
            {
                // Otherwise, it's a simple term
                term = new TermExpression(
                    source,
                    NextColumn(source, context),
                    NextCompareOperator(),
                    NextColumn(source, context));
            }

            if (negate)
            {
                return(new NotExpression(term));
            }
            return(term);
        }
        public static IExpressionEvaluator <Result> ResultEvaluator(TermExpression term)
        {
            switch (term.PropertyName.ToLowerInvariant())
            {
            case "baselinestate":
                return(new EnumEvaluator <Result, BaselineState>(r => r.BaselineState, term));

            case "correlationguid":
                return(new StringEvaluator <Result>(r => r.CorrelationGuid, term, StringComparison.OrdinalIgnoreCase));

            case "guid":
                return(new StringEvaluator <Result>(r => r.Guid, term, StringComparison.OrdinalIgnoreCase));

            case "hostedvieweruri":
                return(new StringEvaluator <Result>(r => r.HostedViewerUri?.ToString(), term, StringComparison.OrdinalIgnoreCase));

            case "kind":
                return(new EnumEvaluator <Result, ResultKind>(r => r.Kind, term));

            case "level":
                return(new EnumEvaluator <Result, FailureLevel>(r => r.Level, term));

            case "message.text":
                return(new StringEvaluator <Result>(r => r.Message?.Text, term, StringComparison.OrdinalIgnoreCase));

            case "occurrencecount":
                return(new LongEvaluator <Result>(r => r.OccurrenceCount, term));

            case "rank":
                return(new DoubleEvaluator <Result>(r => r.Rank, term));

            case "ruleid":
                return(new StringEvaluator <Result>(r => r.RuleId ?? r.Rule?.Id, term, StringComparison.OrdinalIgnoreCase));

            default:
                throw new QueryParseException($"Property Name {term.PropertyName} unrecognized. Known Names: baselineState, correlationGuid, guid, hostedViewerUri, kind, level, message.text, occurrenceCount, rank, ruleId");
            }
        }
Exemple #24
0
        public BoolEvaluator(Func <T, bool> getter, TermExpression term)
        {
            Getter = getter;

            if (!bool.TryParse(term.Value, out bool parsedValue))
            {
                throw new QueryParseException($"{term} value {term.Value} was not a valid boolean.");
            }
            MustEqual = parsedValue;

            switch (term.Operator)
            {
            case CompareOperator.Equals:
                break;

            case CompareOperator.NotEquals:
                MustEqual = !MustEqual;
                break;

            default:
                throw new QueryParseException($"In {term}, {term.PropertyName} is boolean and only supports equals and not equals, not operator {term.Operator}");
            }
        }
Exemple #25
0
        private static void AddTopColumnValues(IntelliSenseResult result, TermExpression lastTerm, IntelliSenseGuidance guidance, List <IntelliSenseItem> suggestions, Table singleTable, ColumnDetails singleColumn)
        {
            // Lame, to turn single terms into AllQuery [normally they return nothing]
            string completeQuery = QueryParser.Parse(result.Complete).ToString();

            // Recommend the top ten values in the column with the prefix typed so far
            DistinctResult topValues = singleTable.Query(new DistinctQueryTop(singleColumn.Name, completeQuery, 10));
            int            total     = (int)topValues.Total;

            if (topValues.Total == 0)
            {
                return;
            }

            // Walk values in order for ==, :, ::, backwards with inverse percentages for !=
            bool isNotEquals = lastTerm.Operator == Operator.NotEquals;
            int  start       = isNotEquals ? topValues.Values.RowCount - 1 : 0;
            int  end         = isNotEquals ? -1 : topValues.Values.RowCount;
            int  step        = isNotEquals ? -1 : 1;

            for (int i = start; i != end; i += step)
            {
                string value         = topValues.Values[i, 0].ToString();
                int    countForValue = (int)topValues.Values[i, 1];
                if (isNotEquals)
                {
                    countForValue = (int)topValues.Total - countForValue;
                }
                double frequency = (double)countForValue / (double)(topValues.Total);

                if ((countForValue > 1 || total <= 10) && value.StartsWith(guidance.Value, StringComparison.OrdinalIgnoreCase))
                {
                    string hint = (countForValue == topValues.Total ? "all" : frequency.ToString("P0"));
                    suggestions.Add(new IntelliSenseItem(QueryTokenCategory.Value, QueryScanner.WrapValue(value), hint));
                }
            }
        }
        public PropertyBagPropertyEvaluator(TermExpression term)
        {
            Match match = s_propertyNameRegex.Match(term.PropertyName);

            _propertyName = match.Groups["name"].Value;

            string prefix = match.Groups["prefix"].Value;

            if (prefix.Equals(RulePropertyPrefix))
            {
                _propertyBelongsToRule = true;
            }
            else if (!prefix.Equals(ResultPropertyPrefix))
            {
                throw new ArgumentException(
                          string.Format(
                              CultureInfo.CurrentCulture,
                              SdkResources.ErrorInvalidQueryPropertyPrefix,
                              "'" + string.Join("', '", ResultPropertyPrefix, RulePropertyPrefix)) + "'",
                          nameof(term));
            }

            _evaluator = CreateEvaluator(term);
        }
        private static bool TryFindSingleMatchingColumn(IReadOnlyCollection <Table> targetTables, TermExpression lastTerm, out Table matchTable, out ColumnDetails matchColumn)
        {
            matchTable  = null;
            matchColumn = null;
            if (lastTerm == null || String.IsNullOrEmpty(lastTerm.ColumnName) || lastTerm.ColumnName == "*")
            {
                return(false);
            }

            foreach (Table table in targetTables)
            {
                foreach (ColumnDetails column in table.ColumnDetails)
                {
                    if (column.Name.Equals(lastTerm.ColumnName, StringComparison.OrdinalIgnoreCase))
                    {
                        // If there's already a match, we have multiple matches
                        if (matchColumn != null)
                        {
                            matchTable  = null;
                            matchColumn = null;
                            return(false);
                        }

                        matchTable  = table;
                        matchColumn = column;
                    }
                }
            }

            return(matchColumn != null);
        }
        /// <summary>
        ///  Get the grammatical categories and value being completed at the given query position.
        ///  This is the pure grammar part of IntelliSense determination.
        /// </summary>
        /// <param name="queryBeforeCursor">Query up to where the cursor is placed</param>
        /// <param name="lastTerm">The TermExpression in progress as parsed</param>
        /// <returns>IntelliSenseGuidance showing the token in progress and possible grammar categories for it</returns>
        internal IntelliSenseGuidance GetCurrentTokenOptions(string queryBeforeCursor, out TermExpression lastTerm, out IExpression query)
        {
            lastTerm = null;
            query    = null;
            IntelliSenseGuidance defaultGuidance = new IntelliSenseGuidance(String.Empty, QueryTokenCategory.Term);

            // If the query is empty, return the guidance for the beginning of the first term
            if (String.IsNullOrEmpty(queryBeforeCursor))
            {
                return(defaultGuidance);
            }

            // Parse the query, asking for hint terms
            query = QueryParser.Parse(queryBeforeCursor, true);

            // If the query had parse errors, return empty guidance
            if (query is EmptyExpression)
            {
                return(new IntelliSenseGuidance(String.Empty, QueryTokenCategory.None));
            }

            // Get the last query term to look at the IntelliSense guidance
            lastTerm = query.GetLastTerm();

            // If no last term, return first term guidance (ex: inside new '('
            if (lastTerm == null)
            {
                return(defaultGuidance);
            }

            // Otherwise, grab the last term guidance
            IntelliSenseGuidance guidance = lastTerm.Guidance;

            return(guidance);
        }
        private static void AddSuggestionsForTerm(IReadOnlyCollection <Table> targetTables, IntelliSenseResult result, TermExpression lastTerm, IntelliSenseGuidance guidance, List <IntelliSenseItem> suggestions)
        {
            if (lastTerm != null && lastTerm.ColumnName == "*")
            {
                object termValue = lastTerm.Value;
                List <Tuple <string, int, int> > columnsForTerm = new List <Tuple <string, int, int> >();

                foreach (Table table in targetTables)
                {
                    DataBlockResult columns = table.Query(new TermInColumnsQuery(termValue.ToString(), GetCompleteQueryPrefix(result)));
                    for (int i = 0; i < columns.Values.RowCount; ++i)
                    {
                        columnsForTerm.Add(new Tuple <string, int, int>((string)columns.Values[i, 0], (int)columns.Values[i, 1], (int)columns.Total));
                    }
                }

                // Sort overall set by frequency descending
                columnsForTerm.Sort((left, right) => ((double)right.Item2 / (double)right.Item3).CompareTo((double)left.Item2 / (double)left.Item3));

                // Add top 10 suggestions
                int countToReturn = Math.Min(10, columnsForTerm.Count);
                for (int i = 0; i < countToReturn; ++i)
                {
                    suggestions.Add(new IntelliSenseItem(QueryTokenCategory.ColumnName, QueryParser.WrapColumnName(columnsForTerm[i].Item1) + " : " + QueryParser.WrapValue(termValue), columnsForTerm[i].Item2, columnsForTerm[i].Item3));
                }
            }
        }
        private static void AddSuggestionsForValue(IReadOnlyCollection <Table> targetTables, IntelliSenseResult result, TermExpression lastTerm, IntelliSenseGuidance guidance, ref bool spaceIsSafeCompletionCharacter, List <IntelliSenseItem> suggestions)
        {
            Table         singleTable;
            ColumnDetails singleColumn;

            if (!TryFindSingleMatchingColumn(targetTables, lastTerm, out singleTable, out singleColumn))
            {
                // If more than one table has the column, we can't recommend anything
                result.SyntaxHint = Value;
            }
            else
            {
                if (lastTerm.Operator == Operator.Equals || lastTerm.Operator == Operator.NotEquals || lastTerm.Operator == Operator.Matches || lastTerm.Operator == Operator.MatchesExact)
                {
                    AddTopColumnValues(result, lastTerm, guidance, suggestions, singleTable, singleColumn);
                }
                else if (lastTerm.Operator == Operator.LessThan || lastTerm.Operator == Operator.LessThanOrEqual || lastTerm.Operator == Operator.GreaterThan || lastTerm.Operator == Operator.GreaterThanOrEqual)
                {
                    AddValueDistribution(result, lastTerm, guidance, suggestions, singleTable, singleColumn);
                }

                Type columnType = singleTable.GetColumnType(singleColumn.Name);

                if (columnType == typeof(ByteBlock))
                {
                    result.SyntaxHint = StringValue;
                }
                else if (columnType == typeof(bool))
                {
                    if (suggestions.Count == 0)
                    {
                        AddWhenPrefixes(BooleanValues, guidance.Value, suggestions);
                    }
                    spaceIsSafeCompletionCharacter = true;
                }
                else if (columnType == typeof(DateTime))
                {
                    result.SyntaxHint = DateTimeValue;
                }
                else if (columnType == typeof(TimeSpan))
                {
                    result.SyntaxHint = TimeSpanValue;
                }
                else if (columnType == typeof(float) || columnType == typeof(double))
                {
                    result.SyntaxHint = FloatValue;
                }
                else if (columnType == typeof(byte) || columnType == typeof(sbyte) || columnType == typeof(short) || columnType == typeof(ushort) || columnType == typeof(int) || columnType == typeof(uint) || columnType == typeof(long) || columnType == typeof(ulong))
                {
                    result.SyntaxHint = IntegerValue;
                }
                else
                {
                    result.SyntaxHint = String.Format("<{0}>", columnType.Name);
                }
            }
        }