Exemple #1
0
        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));
        }
Exemple #2
0
        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));
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
            }
        }
Exemple #5
0
        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);
            }
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        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);
        }