Esempio n. 1
0
        public override bool IsSupportedOpNode(TexlNode node, OperationCapabilityMetadata metadata, TexlBinding binding)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);

            BinaryOpNode binaryOpNode = node?.AsBinaryOp();

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

            var isRHSDelegableTable = IsRHSDelegableTable(binding, binaryOpNode, metadata);

            DName         columnName = default;
            FirstNameInfo info       = null;

            bool isFullyQualifiedFieldAccess = CheckForFullyQualifiedFieldAccess(isRHSDelegableTable, binaryOpNode, binding, node, ref columnName, ref info);

            if (!isFullyQualifiedFieldAccess)
            {
                return(false);
            }

            bool isRowScopedOrLambda = IsRowScopedOrLambda(binding, node, info, columnName, metadata);

            if (!isRowScopedOrLambda)
            {
                return(false);
            }

            return(base.IsSupportedOpNode(node, metadata, binding));
        }
Esempio n. 2
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);
        }
Esempio n. 3
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);
        }
Esempio n. 4
0
        public virtual bool IsSupportedOpNode(TexlNode node, OperationCapabilityMetadata metadata, TexlBinding binding)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);

            BinaryOpNode binaryOpNode = node.AsBinaryOp();

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

            IOpDelegationStrategy opDelStrategy = _function.GetOpDelegationStrategy(binaryOpNode.Op, binaryOpNode);
            var binaryOpDelStrategy             = (opDelStrategy as BinaryOpDelegationStrategy).VerifyValue();

            Contracts.Assert(binaryOpNode.Op == binaryOpDelStrategy.Op);

            // Check if binaryOp is supported by datasource in the context of filter operation.
            // If this is not allowed then there is no point in checking lhs and rhs
            // It's only safe to do so if lhs and rhs is first/dotted name node as columns (FirstName/DottedName node) can have additional capabilities defined.
            if (!(binaryOpNode.Left is FirstNameNode || binaryOpNode.Left is DottedNameNode) &&
                !(binaryOpNode.Right is FirstNameNode || binaryOpNode.Right is DottedNameNode) &&
                !opDelStrategy.IsOpSupportedByTable(metadata, node, binding))
            {
                var telemetryMessage = string.Format("{0} operator not supported at table level", binaryOpNode.Op.ToString());
                SuggestDelegationHintAndAddTelemetryMessage(node, binding, telemetryMessage);
                TrackingProvider.Instance.SetDelegationTrackerStatus(DelegationStatus.BinaryOpNoSupported, node, binding, _function, DelegationTelemetryInfo.CreateBinaryOpNoSupportedInfoTelemetryInfo(binaryOpNode.Op));
                return(false);
            }

            if (!ODataFunctionMappings.BinaryOpToOperatorMap.Value.ContainsKey(binaryOpNode.Op))
            {
                SuggestDelegationHint(node, binding);
                return(false);
            }

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

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

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

            if ((leftType.IsPolymorphic && rightType.IsRecord) || (leftType.IsRecord && rightType.IsPolymorphic))
            {
                return(true);
            }

            if (!DoCoercionCheck(binaryOpNode, metadata, binding))
            {
                SuggestDelegationHint(node, binding);
                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        protected bool IsValidDelegatableFilterPredicateNode(TexlNode dsNode, TexlBinding binding, FilterOpMetadata filterMetadata)
        {
            Contracts.AssertValue(dsNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(filterMetadata);

            var firstNameStrategy  = GetFirstNameNodeDelegationStrategy();
            var dottedNameStrategy = GetDottedNameNodeDelegationStrategy();
            var cNodeStrategy      = GetCallNodeDelegationStrategy();

            NodeKind kind;

            kind = dsNode.Kind;

            switch (kind)
            {
            case NodeKind.BinaryOp:
            {
                BinaryOpNode opNode = dsNode.AsBinaryOp();
                var          binaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op, opNode);
                Contracts.AssertValue(opNode);

                if (!binaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, filterMetadata, binding))
                {
                    return(false);
                }

                break;
            }

            case NodeKind.FirstName:
            {
                if (!firstNameStrategy.IsValidFirstNameNode(dsNode.AsFirstName(), binding, null))
                {
                    return(false);
                }

                break;
            }

            case NodeKind.DottedName:
            {
                if (!dottedNameStrategy.IsValidDottedNameNode(dsNode.AsDottedName(), binding, filterMetadata, null))
                {
                    return(false);
                }

                break;
            }

            case NodeKind.UnaryOp:
            {
                UnaryOpNode opNode = dsNode.AsUnaryOpLit();
                var         unaryOpNodeValidationStrategy = GetOpDelegationStrategy(opNode.Op);
                Contracts.AssertValue(opNode);

                if (!unaryOpNodeValidationStrategy.IsSupportedOpNode(opNode, filterMetadata, binding))
                {
                    SuggestDelegationHint(dsNode, binding);
                    return(false);
                }

                break;
            }

            case NodeKind.Call:
            {
                if (!cNodeStrategy.IsValidCallNode(dsNode.AsCall(), binding, filterMetadata))
                {
                    return(false);
                }

                break;
            }

            default:
            {
                if (kind != NodeKind.BoolLit)
                {
                    SuggestDelegationHint(dsNode, binding, string.Format("Not supported node {0}.", kind));
                    return(false);
                }

                break;
            }
            }

            return(true);
        }