示例#1
0
        public override void Visit(IsOfOp op, System.Data.Entity.Core.Query.InternalTrees.Node n)
        {
            PropertyRefList propertyRefs = new PropertyRefList();

            propertyRefs.Add((PropertyRef)TypeIdPropertyRef.Instance);
            this.AddPropertyRefs(n.Child0, propertyRefs);
            this.VisitChildren(n);
        }
        /// <summary>
        /// IsOfOp handling
        ///
        /// Simply requests the "typeid" property from
        /// the input. No other property is required
        /// </summary>
        /// <param name="op">IsOf op</param>
        /// <param name="n">Node to visit</param>
        public override void Visit(IsOfOp op, Node n)
        {
            // The only property I need from my child is the typeid property;
            PropertyRefList childProps = new PropertyRefList();

            childProps.Add(TypeIdPropertyRef.Instance);
            AddPropertyRefs(n.Child0, childProps);

            VisitChildren(n);
        }
示例#3
0
 /// <summary>
 /// Clone an IsOfOp
 /// </summary>
 /// <param name="op">The Op to Copy</param>
 /// <param name="n">The Node that references the Op</param>
 /// <returns>A copy of the original Node that references a copy of the original Op</returns>
 public override Node Visit(IsOfOp op, Node n)
 {
     if (op.IsOfOnly)
     {
         return(CopyDefault(m_destCmd.CreateIsOfOnlyOp(op.IsOfType), n));
     }
     else
     {
         return(CopyDefault(m_destCmd.CreateIsOfOp(op.IsOfType), n));
     }
 }
示例#4
0
文件: Dump.cs 项目: dox0/DotNet471RS3
 public override void Visit(IsOfOp op, Node n)
 {
     using (new AutoXml(this, (op.IsOfOnly ? "IsOfOnly" : "IsOf")))
     {
         string separator = string.Empty;
         foreach (Node chi in n.Children)
         {
             WriteString(separator);
             VisitNode(chi);
             separator = ",";
         }
     }
 }
        /// <summary>
        ///     IsOf
        ///     Convert an IsOf operator into a typeid comparison:
        ///     IsOfOnly(e, T) => e.TypeId == TypeIdValue(T)
        ///     IsOf(e, T)     => e.TypeId like TypeIdValue(T)% escape null
        /// </summary>
        /// <param name="op"> The IsOfOp to handle </param>
        /// <param name="n"> current isof subtree </param>
        /// <returns> new subtree </returns>
        public override Node Visit(IsOfOp op, Node n)
        {
            // First visit all my children
            VisitChildren(n);

            if (!TypeUtils.IsStructuredType(op.IsOfType))
            {
                return n;
            }
            var typeInfo = m_typeInfo.GetTypeInfo(op.IsOfType);
            var newNode = CreateTypeComparisonOp(n.Child0, typeInfo, op.IsOfOnly);
            return newNode;
        }
        private Node ExpandView(ScanTableOp scanTableOp, ref IsOfOp typeFilter)
        {
            var entitySet = scanTableOp.Table.TableMetadata.Extent;
            PlanCompiler.Assert(entitySet != null, "The target of a ScanTableOp must reference an EntitySet to be used with ExpandView");
            PlanCompiler.Assert(
                entitySet.EntityContainer.DataSpace == DataSpace.CSpace,
                "Store entity sets cannot have Query Mapping Views and should not be used with ExpandView");

            if (typeFilter != null &&
                !typeFilter.IsOfOnly
                &&
                TypeSemantics.IsSubTypeOf(entitySet.ElementType, typeFilter.IsOfType.EdmType))
            {
                //
                // If a type filter is being applied to the ScanTableOp, but that filter is asking
                // for all elements that are the same type or a supertype of the element type of the
                // target entity set, then the type filter is a no-op and can safely be discarded -
                // IF AND ONLY IF the type filter is 'OfType' - which includes subtypes - and NOT
                // 'IsOfOnly' - which requires an exact type match, and so does not include subtypes.
                //
                typeFilter = null;
            }

            //
            // Call the GetGeneratedView method to retrieve the query mapping view for the extent referenced
            // by the ScanTableOp. The actual method used to do this differs depending on whether the default
            // Query Mapping View is sufficient or a targeted view that only filters by element type is required.
            //
            GeneratedView definingQuery = null;
            var requiredType = scanTableOp.Table.TableMetadata.Extent.ElementType;
            var includeSubtypes = true;
            if (typeFilter != null)
            {
                // 
                // A type filter is being applied to the ScanTableOp; it may be possible to produce
                // an optimized expansion of the view based on type-specific views generated for the
                // C-Space entity set. 
                // The type for which the view should be tuned is the 'OfType' specified on the type filter.
                // If the type filter is an 'IsOfOnly' filter then the view should NOT include subtypes of the required type.
                //
                requiredType = (EntityTypeBase)typeFilter.IsOfType.EdmType;
                includeSubtypes = !typeFilter.IsOfOnly;
                if (m_command.MetadataWorkspace.TryGetGeneratedViewOfType(entitySet, requiredType, includeSubtypes, out definingQuery))
                {
                    //
                    // At this point a type-specific view was found that satisifies the type filter's
                    // constraints in terms of required type and whether subtypes should be included;
                    // the type filter itself is now unnecessary and should be set to null indicating
                    // that it can be safely removed (see ProcessScanTableOp and Visit(FilterOp) for this).
                    //
                    typeFilter = null;
                }
            }

            //
            // If a generated view has not been obtained at this point then either:
            // - A type filter was specified but no type-specific view exists that satisfies its constraints.
            //   OR
            // - No type filter was specified.
            // In either case the default query mapping view for the referenced entity set should now be retrieved.
            //
            if (null == definingQuery)
            {
                definingQuery = m_command.MetadataWorkspace.GetGeneratedView(entitySet);
            }

            //
            // If even the default query mapping view was not found then we cannot continue.
            // This implies that the set was not mapped, which should not be allowed, therefore
            // a retail assert is used here instead of a regular exception.
            //
            PlanCompiler.Assert(definingQuery != null, Strings.ADP_NoQueryMappingView(entitySet.EntityContainer.Name, entitySet.Name));

            //
            // At this point we're guaranteed to have found a defining query for the view.
            // We're now going to convert this into an IQT, and then copy it into our own IQT.
            //
            var ret = definingQuery.GetInternalTree(m_command);

            //
            // Make sure we're tracking what we've asked any discriminator maps to contain.
            //
            DetermineDiscriminatorMapUsage(ret, entitySet, requiredType, includeSubtypes);

            //
            // Build up a ScanViewOp to "cap" the defining query below
            //
            var scanViewOp = m_command.CreateScanViewOp(scanTableOp.Table);
            ret = m_command.CreateNode(scanViewOp, ret);

            return ret;
        }
        /// <summary>
        /// Checks to see if this filterOp represents an IS OF (or IS OF ONLY) filter over a ScanTableOp
        /// </summary>
        /// <param name="n">the filterOp node</param>
        /// <param name="ofType">(OUT) the Type to restrict to</param>
        /// <param name="isOfOnly">(OUT) was an ONLY clause specified</param>
        /// <returns></returns>
        private static bool IsOfTypeOverScanTable(Node n, out IsOfOp typeFilter)
        {
            typeFilter = null;

            // 
            // Is the predicate an IsOf predicate
            //
            var isOfOp = n.Child1.Op as IsOfOp;
            if (isOfOp == null)
            {
                return false;
            }
            //
            // Is the Input RelOp a ScanTableOp
            //
            var scanTableOp = n.Child0.Op as ScanTableOp;
            if (scanTableOp == null
                || scanTableOp.Table.Columns.Count != 1)
            {
                return false;
            }
            //
            // Is the argument to the IsOfOp the single column of the table?
            //
            var varRefOp = n.Child1.Child0.Op as VarRefOp;
            if (varRefOp == null
                || varRefOp.Var != scanTableOp.Table.Columns[0])
            {
                return false;
            }

            //
            // All conditions match. Return the info from the IsOf predicate
            //
            typeFilter = isOfOp;
            return true;
        }
        private Node ProcessScanTable(Node scanTableNode, ScanTableOp scanTableOp, ref IsOfOp typeFilter)
        {
            HandleTableOpMetadata(scanTableOp);

            PlanCompiler.Assert(scanTableOp.Table.TableMetadata.Extent != null, "ScanTableOp must reference a table with an extent");

            Node ret = null;

            //
            // Get simple things out of the way. If we're dealing with an S-space entityset, 
            // simply return the node
            // 
            if (scanTableOp.Table.TableMetadata.Extent.EntityContainer.DataSpace
                == DataSpace.SSpace)
            {
                return scanTableNode;
            }
            else
            {
                // "Expand" the C-Space view
                ret = ExpandView(scanTableOp, ref typeFilter);
            }

            // Rerun the processor over the resulting subtree
            ret = VisitNode(ret);

            return ret;
        }
        // Translates 
        //      'R is of T' 
        // to 
        //      '(case when not (R is null) then True else null end) = True'
        //
        // Input requirements:
        //
        //      - IsOfOp and argument to same must be in the same hierarchy.
        //      - IsOfOp and argument must have the same type
        //      - IsOfOp.IsOfType may not have super- or sub- types (validate
        //        using CanRewriteTypeTest)
        //
        // Design requirements:
        //
        //      - Must return true if the record exists
        //      - Must return null if it does not
        //      - Must be in predicate form to avoid confusing SQL gen
        //
        // The translation assumes R is of T when R is non null.
        private Node RewriteIsOfAsIsNull(IsOfOp op, Node n)
        {
            // construct 'R is null' predicate
            var isNullOp = m_command.CreateConditionalOp(OpType.IsNull);
            var isNullNode = m_command.CreateNode(isNullOp, n.Child0);

            // Process the IsNull node to make sure a null sentinel gets added if needed
            ProcessConditionalOp(isNullOp, isNullNode);

            // construct 'not (R is null)' predicate
            var notOp = m_command.CreateConditionalOp(OpType.Not);
            var notNode = m_command.CreateNode(notOp, isNullNode);

            // construct 'True' result
            var trueOp = m_command.CreateConstantOp(op.Type, true);
            var trueNode = m_command.CreateNode(trueOp);

            // construct 'null' default result
            var nullOp = m_command.CreateNullOp(op.Type);
            var nullNode = m_command.CreateNode(nullOp);

            // create case statement
            var caseOp = m_command.CreateCaseOp(op.Type);
            var caseNode = m_command.CreateNode(caseOp, notNode, trueNode, nullNode);

            // create 'case = true' operator
            var equalsOp = m_command.CreateComparisonOp(OpType.EQ);
            var equalsNode = m_command.CreateNode(equalsOp, caseNode, trueNode);

            return equalsNode;
        }
示例#10
0
        /// <summary>
        /// Handler for an IsOfOp.
        /// Keeps track of the IsOfType (if it is a structured type) and rewrites the
        /// operator if the argument is guaranteed to be of type op.IsOfType
        /// </summary>
        /// <param name="op">Current IsOfOp</param>
        /// <param name="n">Current subtree</param>
        /// <returns>Current subtree</returns>
        public override Node Visit(IsOfOp op, Node n)
        {
            VisitScalarOpDefault(op, n); // default handling first
            // keep track of any structured types
            AddTypeReference(op.IsOfType);

            // See if the IsOfOp can be rewritten (if it's not polymorphic)
            if (CanRewriteTypeTest(op.IsOfType.EdmType, n.Child0.Op.Type.EdmType))
            {
                n = RewriteIsOfAsIsNull(op, n);
            }

            // For IsOfOnly(abstract type), suppress DiscriminatorMaps since no explicit type id is available for
            // abstract types.
            if (op.IsOfOnly
                && op.IsOfType.EdmType.Abstract)
            {
                m_suppressDiscriminatorMaps = true;
            }

            return n;
        }
 /// <summary>
 ///     Visitor pattern method for IsOp
 /// </summary>
 /// <param name="op"> The IsOp being visited </param>
 /// <param name="n"> The Node that references the Op </param>
 public virtual void Visit(IsOfOp op, Node n)
 {
     VisitScalarOpDefault(op, n);
 }
        /// <summary>
        ///     IsOfOp handling
        /// 
        ///     Simply requests the "typeid" property from
        ///     the input. No other property is required
        /// </summary>
        /// <param name="op"> IsOf op </param>
        /// <param name="n"> Node to visit </param>
        public override void Visit(IsOfOp op, Node n)
        {
            // The only property I need from my child is the typeid property;
            var childProps = new PropertyRefList();
            childProps.Add(TypeIdPropertyRef.Instance);
            AddPropertyRefs(n.Child0, childProps);

            VisitChildren(n);
        }
示例#13
0
 // <summary>
 // Clone an IsOfOp
 // </summary>
 // <param name="op"> The Op to Copy </param>
 // <param name="n"> The Node that references the Op </param>
 // <returns> A copy of the original Node that references a copy of the original Op </returns>
 public override Node Visit(IsOfOp op, Node n)
 {
     if (op.IsOfOnly)
     {
         return CopyDefault(m_destCmd.CreateIsOfOnlyOp(op.IsOfType), n);
     }
     else
     {
         return CopyDefault(m_destCmd.CreateIsOfOp(op.IsOfType), n);
     }
 }