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; }
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); } }
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}"); } }
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)); } }
/// <summary> /// Build a SetEvaluator given a method to get an IEnumerable<U> 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); }
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<int> 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); }
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); }
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); }
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"); } }
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}"); } }
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); } } }