/// <summary>
 /// SetOp handling
 /// UnionAllOp handling
 /// IntersectOp handling
 /// ExceptOp handling
 ///
 /// Visitor for a SetOp. Pushes desired properties to the corresponding
 /// Vars of the input
 /// </summary>
 /// <param name="op">the setop</param>
 /// <param name="n"></param>
 protected override void VisitSetOp(SetOp op, Node n)
 {
     foreach (VarMap varMap in op.VarMap)
     {
         foreach (KeyValuePair <Var, Var> kv in varMap)
         {
             if (TypeUtils.IsStructuredType(kv.Key.Type))
             {
                 // Get the set of expected properties for the unionVar, and
                 // push it down to the inputvars
                 // For Intersect and ExceptOps, we need all properties
                 // from the input
                 // We call GetPropertyRefList() always to initialize
                 // the map, even though we may not use it
                 //
                 PropertyRefList myProps = GetPropertyRefList(kv.Key);
                 if (op.OpType == OpType.Intersect || op.OpType == OpType.Except)
                 {
                     myProps = PropertyRefList.All;
                     // We "want" all properties even on the output of the setop
                     AddPropertyRefs(kv.Key, myProps);
                 }
                 else
                 {
                     myProps = myProps.Clone();
                 }
                 AddPropertyRefs(kv.Value, myProps);
             }
         }
     }
     VisitChildren(n);
 }
        /// <summary>
        /// SoftCastOp:
        /// If the input is
        ///    Ref - ask for all properties
        ///    Entity, ComplexType - ask for the same properties I've been asked for
        ///    Record - ask for all properties (Note: This should be more optimized in the future
        ///        since we can actually "remap" the properties)
        /// </summary>
        /// <param name="op"></param>
        /// <param name="n"></param>
        public override void Visit(SoftCastOp op, Node n)
        {
            PropertyRefList childProps = null;

            if (md.TypeSemantics.IsReferenceType(op.Type))
            {
                childProps = PropertyRefList.All;
            }
            else if (md.TypeSemantics.IsNominalType(op.Type))
            {
                PropertyRefList myProps = m_nodePropertyRefMap[n];
                childProps = myProps.Clone();
            }
            else if (md.TypeSemantics.IsRowType(op.Type))
            {
                //
                // Note: We should do a better job here (by translating
                // our PropertyRefs to the equivalent property refs on the child
                //
                childProps = PropertyRefList.All;
            }

            if (childProps != null)
            {
                AddPropertyRefs(n.Child0, childProps);
            }
            VisitChildren(n);
        }
        /// <summary>
        /// CaseOp handling
        ///
        /// Pushes its desired properties to each of the WHEN/ELSE clauses
        /// </summary>
        /// <param name="op"></param>
        /// <param name="n"></param>
        public override void Visit(CaseOp op, Node n)
        {
            // First find the properties that my parent expects from me
            PropertyRefList pdProps = GetPropertyRefList(n);

            // push down the same properties to my then/else clauses.
            // the "when" clauses are irrelevant
            for (int i = 1; i < n.Children.Count - 1; i += 2)
            {
                PropertyRefList cdProps = pdProps.Clone();
                AddPropertyRefs(n.Children[i], cdProps);
            }
            AddPropertyRefs(n.Children[n.Children.Count - 1], pdProps.Clone());

            // Now visit the children
            VisitChildren(n);
        }
        /// <summary>
        /// TreatOp handling
        ///
        /// Simply passes down "my" desired properties, and additionally
        /// asks for the TypeID property
        /// </summary>
        /// <param name="op"></param>
        /// <param name="n"></param>
        public override void Visit(TreatOp op, Node n)
        {
            // First find the properties that my parent expects from me
            PropertyRefList pdProps = GetPropertyRefList(n);

            // Push down each of these, and in addition, push down the typeid property
            // to my child
            PropertyRefList childProps = pdProps.Clone();

            childProps.Add(TypeIdPropertyRef.Instance);
            AddPropertyRefs(n.Child0, childProps);
            VisitChildren(n);
        }
        /// <summary>
        /// ScanViewOp
        ///
        /// ask for all properties from the view definition
        /// that have currently been requested from the view itself
        /// </summary>
        /// <param name="op">current ScanViewOp</param>
        /// <param name="n">current node</param>
        public override void Visit(ScanViewOp op, Node n)
        {
            PlanCompiler.Assert(op.Table.Columns.Count == 1, "ScanViewOp with multiple columns?");
            Var             columnVar   = op.Table.Columns[0];
            PropertyRefList columnProps = GetPropertyRefList(columnVar);

            Var inputVar = NominalTypeEliminator.GetSingletonVar(n.Child0);

            PlanCompiler.Assert(inputVar != null, "cannot determine single Var from ScanViewOp's input");

            AddPropertyRefs(inputVar, columnProps.Clone());

            VisitChildren(n);
        }