Exemplo n.º 1
0
        private bool IsColumnNode(TexlNode node, TexlBinding binding)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(binding);

            return((node.Kind == NodeKind.FirstName) && binding.IsRowScope(node));
        }
Exemplo n.º 2
0
        public bool IsValidCallNode(CallNode node, TexlBinding binding, OperationCapabilityMetadata metadata)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(metadata);

            if (!IsValidNode(node, binding))
            {
                SuggestDelegationHint(node, binding);
                return(false);
            }

            // If the node is not row scoped and it's valid then it can be delegated.
            var isRowScoped = binding.IsRowScope(node);

            if (!isRowScoped)
            {
                return(true);
            }

            CallInfo callInfo = binding.GetInfo(node);

            if (callInfo?.Function != null && ((TexlFunction)callInfo.Function).IsRowScopedServerDelegatable(node, binding, metadata))
            {
                return(true);
            }

            var telemetryMessage = string.Format("Kind:{0}, isRowScoped:{1}", node.Kind, isRowScoped);

            SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage);
            TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.UndelegatableFunction, node, binding, _function, DelegationTelemetryInfo.CreateUndelegatableFunctionTelemetryInfo((TexlFunction)callInfo?.Function));
            return(false);
        }
Exemplo n.º 3
0
        public override bool IsServerDelegatable(CallNode callNode, TexlBinding binding)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);

            if (FunctionDelegationCapability.Capabilities == DelegationCapability.None)
            {
                return(false);
            }

            if (!CheckArgsCount(callNode, binding))
            {
                return(false);
            }

            IExternalDataSource dataSource;

            if (!TryGetValidDataSourceForDelegation(callNode, binding, FunctionDelegationCapability, out dataSource))
            {
                if (dataSource != null && dataSource.IsDelegatable)
                {
                    binding.ErrorContainer.EnsureError(DocumentErrorSeverity.Warning, callNode, TexlStrings.OpNotSupportedByServiceSuggestionMessage_OpNotSupportedByService, Name);
                }

                return(false);
            }

            var args = callNode.Args.Children.VerifyValue();

            if (binding.GetType(args[0]).HasExpandInfo ||
                (!binding.IsFullRecordRowScopeAccess(args[1]) && args[1].Kind != NodeKind.FirstName) ||
                !binding.IsRowScope(args[1]) ||
                binding.GetType(args[1]) != DType.Number ||
                ExpressionContainsView(callNode, binding))
            {
                SuggestDelegationHint(callNode, binding);

                if (binding.GetType(args[1]) != DType.Number)
                {
                    DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.NotANumberArgType, callNode, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo());
                }
                else
                {
                    DelegationTrackerCore.SetDelegationTrackerStatus(DelegationStatus.InvalidArgType, callNode, binding, this, DelegationTelemetryInfo.CreateEmptyDelegationTelemetryInfo());
                }

                return(false);
            }

            if (binding.IsFullRecordRowScopeAccess(args[1]))
            {
                return(GetDottedNameNodeDelegationStrategy().IsValidDottedNameNode(args[1].AsDottedName(), binding, null, null));
            }

            var firstNameStrategy = GetFirstNameNodeDelegationStrategy().VerifyValue();

            return(firstNameStrategy.IsValidFirstNameNode(args[1].AsFirstName(), binding, null));
        }
Exemplo n.º 4
0
        private bool DoCoercionCheck(BinaryOpNode binaryOpNode, OperationCapabilityMetadata metadata, TexlBinding binding)
        {
            Contracts.AssertValue(binaryOpNode);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);

            DType leftType  = binding.GetType(binaryOpNode.Left);
            DType rightType = binding.GetType(binaryOpNode.Right);

            switch (leftType.Kind)
            {
            case DKind.Date:
                if (rightType.Kind == DKind.DateTime)
                {
                    // If rhs is a column of type DateTime and lhs is row scoped then we will need to apply the coercion on rhs. So check if coercion function date is supported or not.
                    if (IsColumnNode(binaryOpNode.Right, binding) && binding.IsRowScope(binaryOpNode.Left))
                    {
                        return(IsDelegatableColumnNode(binaryOpNode.Right.AsFirstName(), binding, null, DelegationCapability.Date));
                    }

                    // If lhs is rowscoped but not a field reference and rhs is rowscoped then we need to check if it's supported at table level.
                    if (binding.IsRowScope(binaryOpNode.Left) && binding.IsRowScope(binaryOpNode.Right))
                    {
                        return(metadata.IsDelegationSupportedByTable(DelegationCapability.Date));
                    }

                    return(true);
                }

                break;

            case DKind.DateTime:
                if (rightType.Kind == DKind.Date)
                {
                    // If lhs is a column of type DateTime and RHS is also row scoped then check if coercion function date is supported or not.
                    if (IsColumnNode(binaryOpNode.Left, binding) && binding.IsRowScope(binaryOpNode.Right))
                    {
                        return(IsDelegatableColumnNode(binaryOpNode.Left.AsFirstName(), binding, null, DelegationCapability.Date));
                    }

                    // If lhs is rowscoped but not a field reference and rhs is rowscoped then we need to check if it's supported at table level.
                    if (binding.IsRowScope(binaryOpNode.Left) && binding.IsRowScope(binaryOpNode.Right))
                    {
                        return(metadata.IsDelegationSupportedByTable(DelegationCapability.Date));
                    }

                    return(true);
                }

                break;

            default:
                break;
            }

            return(true);
        }
Exemplo n.º 5
0
        // Verifies if provided column node supports delegation.
        protected bool IsDelegatableColumnNode(FirstNameNode node, TexlBinding binding, IOpDelegationStrategy opDelStrategy, DelegationCapability capability)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(binding);
            Contracts.AssertValueOrNull(opDelStrategy);
            Contracts.Assert(binding.IsRowScope(node));

            FirstNameInfo firstNameInfo = binding.GetInfo(node.AsFirstName());

            if (firstNameInfo == null)
            {
                return(false);
            }

            IDelegationMetadata metadata = GetCapabilityMetadata(firstNameInfo);

            // This means that this row scoped field is from some parent scope which is non-delegatable. That should deny delegation at that point.
            // For this scope, this means that value will be provided from some other source.
            // For example, AddColumns(CDS, "Column1", LookUp(CDS1, Name in FirstName))
            // CDS - *[Name:s], CDS1 - *[FirstName:s]
            if (metadata == null)
            {
                return(true);
            }

            var columnName = firstNameInfo.Name;

            Contracts.AssertValid(columnName);

            var columnPath = DPath.Root.Append(columnName);

            if (!metadata.FilterDelegationMetadata.IsDelegationSupportedByColumn(columnPath, capability))
            {
                var safeColumnName = CharacterUtils.MakeSafeForFormatString(columnName.Value);
                var message        = string.Format(StringResources.Get(TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn), safeColumnName);
                SuggestDelegationHintAndAddTelemetryMessage(node, binding, message, TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn, safeColumnName);
                TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.NoDelSupportByColumn, node, binding, _function, DelegationTelemetryInfo.CreateNoDelSupportByColumnTelemetryInfo(firstNameInfo));
                return(false);
            }

            // If there is any operator applied on this node then check if column supports operation.
            if (opDelStrategy != null && !opDelStrategy.IsOpSupportedByColumn(metadata.FilterDelegationMetadata, node.AsFirstName(), columnPath, binding))
            {
                return(false);
            }

            return(true);
        }
Exemplo n.º 6
0
        public override bool IsRowScopedServerDelegatable(CallNode callNode, TexlBinding binding, OperationCapabilityMetadata metadata)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(metadata);

            if (FunctionDelegationCapability.Capabilities == DelegationCapability.None ||
                binding.ErrorContainer.HasErrors(callNode) ||
                !CheckArgsCount(callNode, binding) ||
                !binding.IsRowScope(callNode))
            {
                return(false);
            }

            TexlNode[] args    = callNode.Args.Children.VerifyValue();
            NodeKind   argKind = args[0].VerifyValue().Kind;

            switch (argKind)
            {
            case NodeKind.FirstName:
            {
                var firstNameStrategy = GetFirstNameNodeDelegationStrategy();
                return(firstNameStrategy.IsValidFirstNameNode(args[0].AsFirstName(), binding, null));
            }

            case NodeKind.Call:
            {
                if (!metadata.IsDelegationSupportedByTable(FunctionDelegationCapability))
                {
                    return(false);
                }

                var cNodeStrategy = GetCallNodeDelegationStrategy();
                return(cNodeStrategy.IsValidCallNode(args[0].AsCall(), binding, metadata));
            }

            case NodeKind.DottedName:
            {
                var dottedStrategy = GetDottedNameNodeDelegationStrategy();
                return(dottedStrategy.IsValidDottedNameNode(args[0].AsDottedName(), binding, metadata, null));
            }

            default:
                break;
            }

            return(false);
        }
Exemplo n.º 7
0
        public override bool IsRowScopedServerDelegatable(CallNode callNode, TexlBinding binding, OperationCapabilityMetadata metadata)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(metadata);

            if (binding.ErrorContainer.HasErrors(callNode))
            {
                return(false);
            }

            if (!CheckArgsCount(callNode, binding))
            {
                return(false);
            }

            TexlNode[] args       = callNode.Args.Children.VerifyValue();
            var        opStrategy = GetOpDelegationStrategy(BinaryOp.Equal, null);

            if (binding.IsFullRecordRowScopeAccess(args[0]))
            {
                return(GetDottedNameNodeDelegationStrategy().IsValidDottedNameNode(args[0] as DottedNameNode, binding, metadata, opStrategy));
            }

            FirstNameNode node = args[0] as FirstNameNode;

            if (node == null)
            {
                var message = string.Format("Arg1 is not a firstname node, instead it is {0}", args[0].Kind);
                AddSuggestionMessageToTelemetry(message, args[0], binding);
                return(false);
            }

            if (!binding.IsRowScope(node))
            {
                return(false);
            }

            var firstNameNodeValidationStrategy = GetFirstNameNodeDelegationStrategy();

            return(firstNameNodeValidationStrategy.IsValidFirstNameNode(node, binding, opStrategy));
        }
Exemplo n.º 8
0
        public bool IsValidFirstNameNode(FirstNameNode node, TexlBinding binding, IOpDelegationStrategy opDelStrategy)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(binding);
            Contracts.AssertValueOrNull(opDelStrategy);

            var isRowScoped = binding.IsRowScope(node);
            var isValid     = IsValidNode(node, binding);

            if (isValid && !isRowScoped)
            {
                return(true);
            }

            // If invalid node then return immediately.
            if (!isValid)
            {
                return(false);
            }

            return(IsDelegatableColumnNode(node, binding, opDelStrategy, _function.FunctionDelegationCapability));
        }
Exemplo n.º 9
0
        protected bool IsRowScopedServerDelegatableHelper(CallNode callNode, TexlBinding binding, OperationCapabilityMetadata metadata)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(metadata);

            if (binding.ErrorContainer.HasErrors(callNode) ||
                !CheckArgsCount(callNode, binding) ||
                !binding.IsRowScope(callNode))
            {
                return(false);
            }

            TexlNode[] args = callNode.Args.Children.VerifyValue();
            Contracts.Assert(args.Length == MinArity);

            if (binding.IsRowScope(args[1]))
            {
                binding.ErrorContainer.EnsureError(DocumentErrorSeverity.Warning, args[1], TexlStrings.SuggestRemoteExecutionHint_StringMatchSecondParam, Name);
                return(false);
            }

            foreach (var arg in args)
            {
                NodeKind argKind = arg.VerifyValue().Kind;
                switch (argKind)
                {
                case NodeKind.FirstName:
                    var firstNameStrategy = GetFirstNameNodeDelegationStrategy();
                    if (!firstNameStrategy.IsValidFirstNameNode(arg.AsFirstName(), binding, null))
                    {
                        return(false);
                    }
                    break;

                case NodeKind.Call:
                    if (!metadata.IsDelegationSupportedByTable(FunctionDelegationCapability))
                    {
                        return(false);
                    }

                    var cNodeStrategy = GetCallNodeDelegationStrategy();
                    if (!cNodeStrategy.IsValidCallNode(arg.AsCall(), binding, metadata))
                    {
                        return(false);
                    }
                    break;

                case NodeKind.StrLit:
                    break;

                case NodeKind.DottedName:
                {
                    var dottedStrategy = GetDottedNameNodeDelegationStrategy();
                    return(dottedStrategy.IsValidDottedNameNode(arg.AsDottedName(), binding, metadata, null));
                }

                default:
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 10
0
        public override bool IsRowScopedServerDelegatable(CallNode callNode, TexlBinding binding, OperationCapabilityMetadata metadata)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(metadata);

            if (binding.ErrorContainer.HasErrors(callNode) ||
                !CheckArgsCount(callNode, binding) ||
                !binding.IsRowScope(callNode))
            {
                return(false);
            }

            TexlNode[] args    = callNode.Args.Children.VerifyValue();
            NodeKind   argKind = args[0].VerifyValue().Kind;

            var opStrategy        = GetOpDelegationStrategy(UnaryOp.Not);
            var firstNameStrategy = GetFirstNameNodeDelegationStrategy();
            var dottedStrategy    = GetDottedNameNodeDelegationStrategy();
            var cNodeStrategy     = GetCallNodeDelegationStrategy();

            switch (argKind)
            {
            case NodeKind.FirstName:
                return(firstNameStrategy.IsValidFirstNameNode(args[0].AsFirstName(), binding, opStrategy));

            case NodeKind.Call:
            {
                if (!opStrategy.IsOpSupportedByTable(metadata, callNode, binding))
                {
                    return(false);
                }

                return(cNodeStrategy.IsValidCallNode(args[0].AsCall(), binding, metadata));
            }

            case NodeKind.BinaryOp:
            {
                if (!opStrategy.IsOpSupportedByTable(metadata, callNode, binding))
                {
                    return(false);
                }

                BinaryOpNode          opNode = args[0].AsBinaryOp();
                IOpDelegationStrategy binaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op, opNode);
                return(binaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, metadata, binding));
            }

            case NodeKind.UnaryOp:
            {
                if (!opStrategy.IsOpSupportedByTable(metadata, callNode, binding))
                {
                    return(false);
                }

                UnaryOpNode opNode = args[0].AsUnaryOpLit();
                var         unaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op);
                return(unaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, metadata, binding));
            }

            case NodeKind.DottedName:
                return(dottedStrategy.IsValidDottedNameNode(args[0].AsDottedName(), binding, metadata, opStrategy));

            default:
                return(argKind == NodeKind.BoolLit);
            }
        }
Exemplo n.º 11
0
        public override bool IsRowScopedServerDelegatable(CallNode callNode, TexlBinding binding, OperationCapabilityMetadata metadata)
        {
            Contracts.AssertValue(callNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(metadata);

            if (binding.ErrorContainer.HasErrors(callNode) ||
                !CheckArgsCount(callNode, binding) ||
                !binding.IsRowScope(callNode))
            {
                return(false);
            }

            TexlNode[] args = callNode.Args.Children.VerifyValue();
            Contracts.Assert(args.Length >= MinArity);

            DelegationCapability funcDelegationCapability = FunctionDelegationCapability | (_isAnd ? DelegationCapability.And : DelegationCapability.Or);

            if (!metadata.IsDelegationSupportedByTable(funcDelegationCapability))
            {
                return(false);
            }

            foreach (var arg in args)
            {
                NodeKind argKind = arg.VerifyValue().Kind;
                switch (argKind)
                {
                case NodeKind.FirstName:
                {
                    var firstNameStrategy = GetFirstNameNodeDelegationStrategy();
                    if (!firstNameStrategy.IsValidFirstNameNode(arg.AsFirstName(), binding, null))
                    {
                        return(false);
                    }

                    break;
                }

                case NodeKind.Call:
                {
                    var cNodeStrategy = GetCallNodeDelegationStrategy();
                    if (!cNodeStrategy.IsValidCallNode(arg.AsCall(), binding, metadata))
                    {
                        SuggestDelegationHint(arg, binding);
                        return(false);
                    }

                    break;
                }

                case NodeKind.DottedName:
                {
                    var dottedStrategy = GetDottedNameNodeDelegationStrategy();
                    if (!dottedStrategy.IsValidDottedNameNode(arg.AsDottedName(), binding, metadata, null))
                    {
                        SuggestDelegationHint(arg, binding);
                        return(false);
                    }

                    break;
                }

                case NodeKind.BinaryOp:
                {
                    BinaryOpNode opNode = arg.AsBinaryOp();
                    var          binaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op, opNode);
                    if (!binaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, metadata, binding))
                    {
                        SuggestDelegationHint(arg, binding);
                        return(false);
                    }

                    break;
                }

                case NodeKind.UnaryOp:
                {
                    UnaryOpNode opNode = arg.AsUnaryOpLit();
                    var         unaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op);
                    if (!unaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, metadata, binding))
                    {
                        SuggestDelegationHint(arg, binding);
                        return(false);
                    }

                    break;
                }

                case NodeKind.BoolLit:
                    break;

                default:
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 12
0
        // Verifies if given kind of node is supported by function delegation.
        private bool IsSupportedNode(TexlNode node, OperationCapabilityMetadata metadata, TexlBinding binding, IOpDelegationStrategy opDelStrategy, bool isRHSNode)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(opDelStrategy);

            if (!binding.IsRowScope(node))
            {
                // Check whether this is -
                //  1) in operator delegation and
                //  2) it is verifying if RHS node is supported and
                //  3) it is not an async node and
                //  4) it is a single column table and
                //  5) metadata belongs to cds datasource that supports delegation of CdsIn
                // If this check fails, verify if it is simply a valid node..
                // Eg of valid delegation functions -
                // Filter(Accounts, 'Account Name' in ["Foo", Bar"]) - Direct table use
                // Set(Names, ["Foo", Bar"]); Filter(Accounts, 'Account Name' in Names) - Using variable of type table
                // ClearCollect(Names, Accounts); Filter(Accounts, 'Account Name' in Names.'Account Name') - using column from collection.
                // This won't be delegated - Filter(Accounts, 'Account Name' in Accounts.'Account Name') as Accounts.'Account Name' is async.
                if ((binding.Document.Properties.EnabledFeatures.IsEnhancedDelegationEnabled &&
                     isRHSNode && (opDelStrategy as BinaryOpDelegationStrategy)?.Op == BinaryOp.In && !binding.IsAsync(node) && binding.GetType(node).IsTable&& binding.GetType(node).IsColumn&&
                     metadata.IsDelegationSupportedByTable(DelegationCapability.CdsIn)) ||
                    IsValidNode(node, binding))
                {
                    return(true);
                }
            }

            switch (node.Kind)
            {
            case NodeKind.DottedName:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                var dottedNodeValStrategy = _function.GetDottedNameNodeDelegationStrategy();
                return(dottedNodeValStrategy.IsValidDottedNameNode(node.AsDottedName(), binding, metadata, opDelStrategy));
            }

            case NodeKind.Call:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                var cNodeValStrategy = _function.GetCallNodeDelegationStrategy();
                return(cNodeValStrategy.IsValidCallNode(node.AsCall(), binding, metadata));
            }

            case NodeKind.FirstName:
            {
                var firstNameNodeValStrategy = _function.GetFirstNameNodeDelegationStrategy();
                return(firstNameNodeValStrategy.IsValidFirstNameNode(node.AsFirstName(), binding, opDelStrategy));
            }

            case NodeKind.UnaryOp:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                var unaryopNode = node.AsUnaryOpLit();
                IOpDelegationStrategy unaryOpNodeDelegationStrategy = _function.GetOpDelegationStrategy(unaryopNode.Op);
                return(unaryOpNodeDelegationStrategy.IsSupportedOpNode(unaryopNode, metadata, binding));
            }

            case NodeKind.BinaryOp:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                var binaryOpNode = node.AsBinaryOp().VerifyValue();
                opDelStrategy = _function.GetOpDelegationStrategy(binaryOpNode.Op, binaryOpNode);

                var binaryOpDelStrategy = (opDelStrategy as BinaryOpDelegationStrategy).VerifyValue();
                Contracts.Assert(binaryOpNode.Op == binaryOpDelStrategy.Op);

                if (!opDelStrategy.IsSupportedOpNode(node, metadata, binding))
                {
                    SuggestDelegationHint(binaryOpNode, binding);
                    return(false);
                }

                break;
            }

            default:
            {
                var kind = node.Kind;
                if (kind != NodeKind.BoolLit && kind != NodeKind.StrLit && kind != NodeKind.NumLit)
                {
                    var telemetryMessage = string.Format("NodeKind {0} unsupported.", kind);
                    SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage);
                    return(false);
                }

                break;
            }
            }

            return(true);
        }
Exemplo n.º 13
0
        private bool IsSupportedNode(TexlNode node, OperationCapabilityMetadata metadata, TexlBinding binding, IOpDelegationStrategy opDelStrategy)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(opDelStrategy);

            if (!binding.IsRowScope(node))
            {
                return(true);
            }

            switch (node.Kind)
            {
            case NodeKind.DottedName:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                var dottedNodeValStrategy = _function.GetDottedNameNodeDelegationStrategy();
                return(dottedNodeValStrategy.IsValidDottedNameNode(node.AsDottedName(), binding, metadata, opDelStrategy));
            }

            case NodeKind.Call:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                var cNodeValStrategy = _function.GetCallNodeDelegationStrategy();
                return(cNodeValStrategy.IsValidCallNode(node.AsCall(), binding, metadata));
            }

            case NodeKind.FirstName:
            {
                var firstNameNodeValStrategy = _function.GetFirstNameNodeDelegationStrategy();
                return(firstNameNodeValStrategy.IsValidFirstNameNode(node.AsFirstName(), binding, opDelStrategy));
            }

            case NodeKind.UnaryOp:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                UnaryOpNode unaryOpNode = node.AsUnaryOpLit().VerifyValue();
                opDelStrategy = _function.GetOpDelegationStrategy(unaryOpNode.Op).VerifyValue();

                var unaryOpDelStrategy = (opDelStrategy as UnaryOpDelegationStrategy).VerifyValue();
                Contracts.Assert(unaryOpDelStrategy.Op == unaryOpNode.Op);

                if (!opDelStrategy.IsSupportedOpNode(node, metadata, binding))
                {
                    SuggestDelegationHint(node, binding);
                    return(false);
                }

                return(true);
            }

            case NodeKind.BinaryOp:
            {
                if (!opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
                {
                    return(false);
                }

                var binaryOpNode = node.AsBinaryOp().VerifyValue();
                IOpDelegationStrategy binaryOpNodeDelValidationStrategy = _function.GetOpDelegationStrategy(binaryOpNode.Op, binaryOpNode);
                return(binaryOpNodeDelValidationStrategy.IsSupportedOpNode(node.AsBinaryOp(), metadata, binding));
            }
            }

            SuggestDelegationHint(node, binding);
            return(false);
        }
Exemplo n.º 14
0
        public bool IsValidDottedNameNode(DottedNameNode node, TexlBinding binding, OperationCapabilityMetadata metadata, IOpDelegationStrategy opDelStrategy)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(binding);
            Contracts.AssertValueOrNull(opDelStrategy);

            var isRowScoped = binding.IsRowScope(node);

            if (!isRowScoped)
            {
                return(IsValidNode(node, binding));
            }

            bool isRowScopedDelegationExempted;

            if (!IsValidRowScopedDottedNameNode(node, binding, metadata, out isRowScopedDelegationExempted))
            {
                var telemetryMessage = string.Format("Kind:{0}, isRowScoped:{1}",
                                                     node.Kind, isRowScoped);

                SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage);
                return(false);
            }

            if (isRowScopedDelegationExempted)
            {
                binding.SetBlockScopedConstantNode(node);
                return(true);
            }

            if (binding.TryGetFullRecordRowScopeAccessInfo(node, out var firstNameInfo))
            {
                // This means that this row scoped field is from some parent scope which is non-delegatable. That should deny delegation at that point.
                // For this scope, this means that value will be provided from some other source.
                // For example, AddColumns(CDS As Left, "Column1", LookUp(CDS1, Left.Name in FirstName))
                // CDS - *[Name:s], CDS1 - *[FirstName:s]
                if (GetCapabilityMetadata(firstNameInfo) == null)
                {
                    return(true);
                }
            }

            if (!binding.GetType(node.Left).HasExpandInfo)
            {
                DPath columnPath;
                if (!BinderUtils.TryConvertNodeToDPath(binding, node, out columnPath) || !metadata.IsDelegationSupportedByColumn(columnPath, _function.FunctionDelegationCapability))
                {
                    var safeColumnName = CharacterUtils.MakeSafeForFormatString(columnPath.ToDottedSyntax());
                    var message        = string.Format(StringResources.Get(TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn), safeColumnName);
                    SuggestDelegationHintAndAddTelemetryMessage(node, binding, message, TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn, safeColumnName);
                    TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.NoDelSupportByColumn, node, binding, _function, DelegationTelemetryInfo.CreateNoDelSupportByColumnTelemetryInfo(columnPath.ToDottedSyntax()));
                    return(false);
                }

                // If there is any operator applied on this node then check if column supports operation.
                return(opDelStrategy?.IsOpSupportedByColumn(metadata, node, columnPath, binding) ?? true);
            }

            // If there is an entity reference then we need to do additional verification.
            IExpandInfo info           = binding.GetType(node.Left).ExpandInfo.VerifyValue();
            var         dataSourceInfo = info.ParentDataSource;

            IDataEntityMetadata entityMetadata;

            if (!dataSourceInfo.DataEntityMetadataProvider.TryGetEntityMetadata(info.Identity, out entityMetadata))
            {
                var telemetryMessage = string.Format("Kind:{0}, isRowScoped:{1}, no metadata found for entity {2}",
                                                     node.Kind, isRowScoped, CharacterUtils.MakeSafeForFormatString(info.Identity));

                SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage);
                return(false);
            }

            OperationCapabilityMetadata entityCapabilityMetadata = GetScopedOperationCapabilityMetadata(entityMetadata.DelegationMetadata);
            string maybeLogicalName;
            DName  columnName = node.Right.Name;

            if (entityMetadata.DisplayNameMapping.TryGetFromSecond(node.Right.Name.Value, out maybeLogicalName))
            {
                columnName = new DName(maybeLogicalName);
            }

            var entityColumnPath = DPath.Root.Append(columnName);

            if (!entityCapabilityMetadata.IsDelegationSupportedByColumn(entityColumnPath, _function.FunctionDelegationCapability))
            {
                var safeColumnName = CharacterUtils.MakeSafeForFormatString(columnName.Value);
                var message        = string.Format(StringResources.Get(TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn), safeColumnName);
                SuggestDelegationHintAndAddTelemetryMessage(node, binding, message, TexlStrings.OpNotSupportedByColumnSuggestionMessage_OpNotSupportedByColumn, safeColumnName);
                TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.NoDelSupportByColumn, node, binding, _function, DelegationTelemetryInfo.CreateNoDelSupportByColumnTelemetryInfo(columnName));
                return(false);
            }

            // If there is any operator applied on this node then check if column supports operation.
            return(opDelStrategy?.IsOpSupportedByColumn(entityCapabilityMetadata, node, entityColumnPath, binding) ?? true);
        }