private bool IsSortOrderSuppportedByColumn(string order, SortOpMetadata metadata, DPath columnPath) { Contracts.AssertValue(order); Contracts.AssertValue(metadata); Contracts.AssertValid(columnPath); order = order.ToLower(); // If column is marked as ascending only then return false if order requested is descending. return(order != Microsoft.PowerFx.Core.Utils.LanguageConstants.DescendingSortOrderString || !metadata.IsColumnAscendingOnly(columnPath)); }
private bool IsValidSortableColumnNode(TexlNode node, TexlBinding binding, SortOpMetadata metadata) { Contracts.AssertValue(node); Contracts.AssertValue(binding); Contracts.AssertValue(metadata); if (binding.ErrorContainer.HasErrors(node) || node.Kind != NodeKind.StrLit) { return(false); } var columnName = node.AsStrLit().VerifyValue(); return(IsColumnSortable(columnName, binding, metadata)); }
private bool IsColumnSortable(StrLitNode node, TexlBinding binding, SortOpMetadata sortMetadata) { Contracts.AssertValue(node); Contracts.AssertValue(binding); Contracts.AssertValue(sortMetadata); DPath columnPath = DPath.Root.Append(new DName(node.Value)); if (!sortMetadata.IsDelegationSupportedByColumn(columnPath, DelegationCapability.Sort)) { SuggestDelegationHint(node, binding); return(false); } return(true); }
private bool IsValidSortOrderNode(TexlNode node, SortOpMetadata metadata, TexlBinding binding, DPath columnPath) { Contracts.AssertValue(node); Contracts.AssertValue(metadata); Contracts.AssertValue(binding); Contracts.AssertValid(columnPath); if (binding.IsAsync(node)) { var message = string.Format("Function:{0}, SortOrderNode is async", Name); AddSuggestionMessageToTelemetry(message, node, binding); return(false); } string sortOrder; switch (node.Kind) { case NodeKind.FirstName: case NodeKind.StrLit: return(_sortOrderValidator.TryGetValidValue(node, binding, out sortOrder) && IsSortOrderSuppportedByColumn(sortOrder, metadata, columnPath)); case NodeKind.DottedName: case NodeKind.Call: if (_sortOrderValidator.TryGetValidValue(node, binding, out sortOrder) && IsSortOrderSuppportedByColumn(sortOrder, metadata, columnPath)) { return(true); } // If both ascending and descending are supported then we can support this. return(IsSortOrderSuppportedByColumn(Microsoft.PowerFx.Core.Utils.LanguageConstants.DescendingSortOrderString, metadata, columnPath) && IsSortOrderSuppportedByColumn(Microsoft.PowerFx.Core.Utils.LanguageConstants.AscendingSortOrderString, metadata, columnPath)); default: AddSuggestionMessageToTelemetry("Unsupported sortorder node.", node, binding); return(false); } }
private bool IsValidSortOrderNode(TexlNode node, SortOpMetadata metadata, TexlBinding binding, DPath columnPath) { Contracts.AssertValue(node); Contracts.AssertValue(metadata); Contracts.AssertValue(binding); Contracts.AssertValid(columnPath); if (binding.IsAsync(node)) { AddSuggestionMessageToTelemetry("Async sortorder node.", node, binding); DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.AsyncSortOrder, node, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo()); return(false); } string sortOrder; switch (node.Kind) { case NodeKind.FirstName: case NodeKind.StrLit: return(_sortOrderValidator.TryGetValidValue(node, binding, out sortOrder) && IsSortOrderSuppportedByColumn(node, binding, sortOrder, metadata, columnPath)); case NodeKind.DottedName: case NodeKind.Call: if (_sortOrderValidator.TryGetValidValue(node, binding, out sortOrder) && IsSortOrderSuppportedByColumn(node, binding, sortOrder, metadata, columnPath)) { return(true); } // If both ascending and descending are supported then we can support this. return(IsSortOrderSuppportedByColumn(node, binding, LanguageConstants.DescendingSortOrderString, metadata, columnPath) && IsSortOrderSuppportedByColumn(node, binding, LanguageConstants.AscendingSortOrderString, metadata, columnPath)); default: AddSuggestionMessageToTelemetry("Unsupported sortorder node kind.", node, binding); return(false); } }
public override bool IsServerDelegatable(CallNode callNode, TexlBinding binding) { Contracts.AssertValue(callNode); Contracts.AssertValue(binding); if (binding.ErrorContainer.HasErrors(callNode)) { return(false); } if (!CheckArgsCount(callNode, binding)) { return(false); } SortOpMetadata metadata = null; IDelegationMetadata delegationMetadata = null; IExternalDataSource dataSource; if (TryGetEntityMetadata(callNode, binding, out delegationMetadata)) { if (!binding.Document.Properties.EnabledFeatures.IsEnhancedDelegationEnabled || !TryGetValidDataSourceForDelegation(callNode, binding, DelegationCapability.ArrayLookup, out _)) { SuggestDelegationHint(callNode, binding); return(false); } metadata = delegationMetadata.SortDelegationMetadata.VerifyValue(); } else { if (!TryGetValidDataSourceForDelegation(callNode, binding, DelegationCapability.Sort, out dataSource)) { return(false); } metadata = dataSource.DelegationMetadata.SortDelegationMetadata; } TexlNode[] args = callNode.Args.Children.VerifyValue(); int cargs = args.Count(); const string defaultSortOrder = Microsoft.PowerFx.Core.Utils.LanguageConstants.AscendingSortOrderString; for (int i = 1; i < cargs; i += 2) { if (!IsValidSortableColumnNode(args[i], binding, metadata)) { SuggestDelegationHint(args[i], binding); return(false); } string columnName = args[i].AsStrLit().VerifyValue().Value; TexlNode sortOrderNode = (i + 1) < cargs ? args[i + 1] : null; string sortOrder = sortOrderNode == null ? defaultSortOrder : ""; if (sortOrderNode != null) { if (!IsValidSortOrderNode(sortOrderNode, metadata, binding, DPath.Root.Append(new DName(columnName)))) { SuggestDelegationHint(sortOrderNode, binding); return(false); } } else if (!IsSortOrderSuppportedByColumn(sortOrder, metadata, DPath.Root.Append(new DName(columnName)))) { SuggestDelegationHint(args[i], binding); return(false); } } return(true); }
private bool IsSortOrderSuppportedByColumn(TexlNode node, TexlBinding binding, string order, SortOpMetadata metadata, DPath columnPath) { Contracts.AssertValue(node); Contracts.AssertValue(binding); Contracts.AssertValue(order); Contracts.AssertValue(metadata); Contracts.AssertValid(columnPath); var result = IsSortOrderSuppportedByColumn(order, metadata, columnPath); if (!result) { DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.SortOrderNotSupportedByColumn, node, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo()); } return(result); }
public override bool IsServerDelegatable(CallNode callNode, TexlBinding binding) { Contracts.AssertValue(callNode); Contracts.AssertValue(binding); if (!CheckArgsCount(callNode, binding)) { return(false); } SortOpMetadata metadata = null; IDelegationMetadata delegationMetadata = null; IExternalDataSource dataSource; if (TryGetEntityMetadata(callNode, binding, out delegationMetadata)) { if (!binding.Document.Properties.EnabledFeatures.IsEnhancedDelegationEnabled || !TryGetValidDataSourceForDelegation(callNode, binding, DelegationCapability.ArrayLookup, out _)) { SuggestDelegationHint(callNode, binding); return(false); } metadata = delegationMetadata.SortDelegationMetadata.VerifyValue(); } else { if (!TryGetValidDataSourceForDelegation(callNode, binding, DelegationCapability.Sort, out dataSource)) { return(false); } metadata = dataSource.DelegationMetadata.SortDelegationMetadata; } TexlNode[] args = callNode.Args.Children.VerifyValue(); TexlNode arg1 = args[1].VerifyValue(); // For now, we are only supporting delegation for Sort operations where second argument is column name. // For example, Sort(CDS, Value) FirstNameNode firstName = arg1.AsFirstName(); if (firstName == null) { SuggestDelegationHint(arg1, binding); AddSuggestionMessageToTelemetry("Arg1 is not a FirstName node.", arg1, binding); DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.UnSupportedSortArg, arg1, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo()); return(false); } FirstNameInfo firstNameInfo = binding.GetInfo(firstName); if (firstNameInfo == null) { return(false); } DPath columnName = DPath.Root.Append(firstNameInfo.Name); if (!metadata.IsDelegationSupportedByColumn(columnName, DelegationCapability.Sort)) { SuggestDelegationHint(firstName, binding); DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.NoDelSupportByColumn, firstName, binding, this, DelegationTelemetryInfo.CreateNoDelSupportByColumnTelemetryInfo(firstNameInfo)); return(false); } const string defaultSortOrder = LanguageConstants.AscendingSortOrderString; int cargs = args.Count(); // Verify that the third argument (If present) is an Enum or string literal. if (cargs < 3 && IsSortOrderSuppportedByColumn(callNode, binding, defaultSortOrder, metadata, columnName)) { return(true); } // TASK: 6237100 - Binder: Propagate errors in subtree of the callnode to the call node itself // Only FirstName, DottedName and StrLit non-async nodes are supported for arg2. TexlNode arg2 = args[2].VerifyValue(); if (!IsValidSortOrderNode(arg2, metadata, binding, columnName)) { SuggestDelegationHint(arg2, binding); return(false); } return(true); }