protected override void VisitSetOp(SetOp op, Node n) { Dictionary <string, object> attrs = new Dictionary <string, object>(); if (OpType.UnionAll == op.OpType) { UnionAllOp unionAllOp = (UnionAllOp)op; if (unionAllOp.BranchDiscriminator != null) { attrs.Add("branchDiscriminator", (object)unionAllOp.BranchDiscriminator); } } using (new Dump.AutoXml(this, (Op)op, attrs)) { using (new Dump.AutoXml(this, "outputs")) { foreach (Var output in op.Outputs) { this.DumpVar(output); } } int num = 0; foreach (Node child in n.Children) { using (new Dump.AutoXml(this, "input", new Dictionary <string, object>() { { "VarMap", (object)op.VarMap[num++].ToString() } })) this.VisitNode(child); } } }
protected override void VisitSetOp(SetOp op, Node n) { var attrs = new Dictionary <string, object>(); if (OpType.UnionAll == op.OpType) { var uallOp = (UnionAllOp)op; if (null != uallOp.BranchDiscriminator) { attrs.Add("branchDiscriminator", uallOp.BranchDiscriminator); } } using (new AutoXml(this, op, attrs)) { using (new AutoXml(this, "outputs")) { foreach (var v in op.Outputs) { DumpVar(v); } } var i = 0; foreach (var chi in n.Children) { var attrs2 = new Dictionary <string, object>(); attrs2.Add("VarMap", op.VarMap[i++].ToString()); using (new AutoXml(this, "input", attrs2)) { VisitNode(chi); } } } }
// <summary> // Common copy path for all SetOps // </summary> // <param name="op"> The SetOp to Copy (must be one of ExceptOp, IntersectOp, UnionAllOp) </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> private Node CopySetOp(SetOp op, Node n) { // Visit the Node's children and map their Vars var children = ProcessChildren(n); var leftMap = new VarMap(); var rightMap = new VarMap(); foreach (var kv in op.VarMap[0]) { // Create a new output Var that is a copy of the original output Var Var outputVar = m_destCmd.CreateSetOpVar(kv.Key.Type); // Add a mapping for the new output var we've just created SetMappedVar(kv.Key, outputVar); // Add this output var's entries to the new VarMaps leftMap.Add(outputVar, GetMappedVar(kv.Value)); rightMap.Add(outputVar, GetMappedVar((op.VarMap[1])[kv.Key])); } SetOp newSetOp = null; switch (op.OpType) { case OpType.UnionAll: { var branchDiscriminator = ((UnionAllOp)op).BranchDiscriminator; if (null != branchDiscriminator) { branchDiscriminator = GetMappedVar(branchDiscriminator); } newSetOp = m_destCmd.CreateUnionAllOp(leftMap, rightMap, branchDiscriminator); } break; case OpType.Intersect: { newSetOp = m_destCmd.CreateIntersectOp(leftMap, rightMap); } break; case OpType.Except: { newSetOp = m_destCmd.CreateExceptOp(leftMap, rightMap); } break; default: { Debug.Assert(false, "Unexpected SetOpType"); } break; } return(m_destCmd.CreateNode(newSetOp, children)); }
protected override void VisitSetOp(SetOp op, Node n) { VisitRelOpDefault(op, n); AssertRelOpOrPhysicalOp(n.Child0.Op); AssertRelOpOrPhysicalOp(n.Child1.Op); // // Ensure that the corresponding setOp Vars are all of the same // type // foreach (var varMap in op.VarMap) { foreach (var kv in varMap) { AssertEqualTypes(kv.Key.Type, kv.Value.Type); } } }
private Node CopySetOp(SetOp op, Node n) { List <Node> args = this.ProcessChildren(n); VarMap leftMap = new VarMap(); VarMap rightMap = new VarMap(); foreach (KeyValuePair <Var, Var> keyValuePair in (Dictionary <Var, Var>)op.VarMap[0]) { Var setOpVar = (Var)this.m_destCmd.CreateSetOpVar(keyValuePair.Key.Type); this.SetMappedVar(keyValuePair.Key, setOpVar); leftMap.Add(setOpVar, this.GetMappedVar(keyValuePair.Value)); rightMap.Add(setOpVar, this.GetMappedVar(op.VarMap[1][keyValuePair.Key])); } SetOp setOp = (SetOp)null; switch (op.OpType) { case OpType.UnionAll: Var var = ((UnionAllOp)op).BranchDiscriminator; if (var != null) { var = this.GetMappedVar(var); } setOp = (SetOp)this.m_destCmd.CreateUnionAllOp(leftMap, rightMap, var); break; case OpType.Intersect: setOp = (SetOp)this.m_destCmd.CreateIntersectOp(leftMap, rightMap); break; case OpType.Except: setOp = (SetOp)this.m_destCmd.CreateExceptOp(leftMap, rightMap); break; } return(this.m_destCmd.CreateNode((Op)setOp, args)); }
/// <summary> /// SetOp /// Converts all SetOps - union/intersect/except. /// Calls VisitChildren() to do the bulk of the work. After that, the VarMaps /// need to be updated to reflect the removal of any structured Vars /// </summary> /// <param name="op"> </param> /// <param name="n"> </param> /// <returns> new subtree </returns> protected override Node VisitSetOp(SetOp op, Node n) { VisitChildren(n); // Now walk through the first VarMap, and identify the Vars that are needed for (var i = 0; i < op.VarMap.Length; i++) { List<ComputedVar> newComputedVars; op.VarMap[i] = FlattenVarMap(op.VarMap[i], out newComputedVars); if (newComputedVars != null) { n.Children[i] = FixupSetOpChild(n.Children[i], op.VarMap[i], newComputedVars); } } // now get the set of Vars that we will actually need op.Outputs.Clear(); foreach (var v in op.VarMap[0].Keys) { op.Outputs.Set(v); } return n; }
/// <summary> /// Computes a NodeInfo for SetOps (UnionAll, Intersect, Except). /// Definitions = OutputVars /// LocalDefinitions = OutputVars /// Keys = Output Vars for Intersect, Except. For UnionAll ?? /// External References = any external references from the inputs /// RowCount: Min = 0, Max = unbounded. /// For UnionAlls, MinRows = max(MinRows of left and right inputs) /// NonNullable definitions = /// UnionAll - Columns that are NonNullableDefinitions on both (children) sides /// Except - Columns that are NonNullableDefinitions on the left child side /// Intersect - Columns that are NonNullableDefinitions on either side /// NonNullableInputDefinitions = default(empty) because cannot be used /// </summary> /// <param name="op"> The SetOp </param> /// <param name="n"> corresponding Node </param> protected override NodeInfo VisitSetOp(SetOp op, Node n) { var nodeInfo = InitExtendedNodeInfo(n); // My definitions and my "all" definitions are simply my outputs nodeInfo.Definitions.InitFrom(op.Outputs); nodeInfo.LocalDefinitions.InitFrom(op.Outputs); var leftChildNodeInfo = GetExtendedNodeInfo(n.Child0); var rightChildNodeInfo = GetExtendedNodeInfo(n.Child1); var minRows = RowCount.Zero; // My external references are the external references of both of // my inputs nodeInfo.ExternalReferences.Or(leftChildNodeInfo.ExternalReferences); nodeInfo.ExternalReferences.Or(rightChildNodeInfo.ExternalReferences); if (op.OpType == OpType.UnionAll) { minRows = (leftChildNodeInfo.MinRows > rightChildNodeInfo.MinRows) ? leftChildNodeInfo.MinRows : rightChildNodeInfo.MinRows; } // for intersect, and exceptOps, the keys are simply the outputs. if (op.OpType == OpType.Intersect || op.OpType == OpType.Except) { nodeInfo.Keys.InitFrom(op.Outputs); } else { // UnionAlls are a lot more complicated. If we've gone through // keyPullup, we will have set some keys on it's input branches and // what we need to do here is get the keys from each branch and re-map // them to the output vars. // // If the branchDiscriminator is not set on the unionAllOp, then // we haven't been through key pullup and we can't look at the keys // that the child nodes have, because they're not discriminated. // // See the logic in KeyPullup, where we make sure that there are // actually branch discriminators on the input branches. var unionAllOp = (UnionAllOp)op; if (null == unionAllOp.BranchDiscriminator) { nodeInfo.Keys.NoKeys = true; } else { var nodeKeys = m_command.CreateVarVec(); VarVec mappedKeyVec; for (var i = 0; i < n.Children.Count; i++) { var childNodeInfo = n.Children[i].GetExtendedNodeInfo(m_command); if (!childNodeInfo.Keys.NoKeys && !childNodeInfo.Keys.KeyVars.IsEmpty) { mappedKeyVec = childNodeInfo.Keys.KeyVars.Remap(unionAllOp.VarMap[i].GetReverseMap()); nodeKeys.Or(mappedKeyVec); } else { // Each branch had better have keys, or we can't continue. nodeKeys.Clear(); break; } } // You might be tempted to ask: "Don't we need to add the branch discriminator // to the keys as well?" The reason we don't is that we wouldn't be here unless // we have a branch discriminator variable, which implies we've pulled up keys on // the inputs, and they'll already have the branch descriminator set in the keys // of each input, so we don't need to add that... if (nodeKeys.IsEmpty) { nodeInfo.Keys.NoKeys = true; } else { nodeInfo.Keys.InitFrom(nodeKeys); } } } //Non-nullable definitions var leftNonNullableVars = leftChildNodeInfo.NonNullableDefinitions.Remap(op.VarMap[0].GetReverseMap()); nodeInfo.NonNullableDefinitions.InitFrom(leftNonNullableVars); if (op.OpType != OpType.Except) { var rightNonNullableVars = rightChildNodeInfo.NonNullableDefinitions.Remap(op.VarMap[1].GetReverseMap()); if (op.OpType == OpType.Intersect) { nodeInfo.NonNullableDefinitions.Or(rightNonNullableVars); } else //Union all { nodeInfo.NonNullableDefinitions.And(rightNonNullableVars); } } nodeInfo.NonNullableDefinitions.And(op.Outputs); nodeInfo.MinRows = minRows; return(nodeInfo); }
/// <summary> /// Default handler for all SetOps /// </summary> /// <param name="op"> set op </param> /// <param name="n"> </param> protected virtual void VisitSetOp(SetOp op, Node n) { VisitRelOpDefault(op, n); }
/// <summary> /// Does the list of outputs of the given SetOp contain a var /// from the given VarVec defined by the SetOp's child with the given index /// </summary> private static bool HasVarReferences(SetOp op, VarVec vars, int index) { foreach (var var in op.VarMap[index].Values) { if (vars.IsSet(var)) { return true; } } return false; }
protected virtual void VisitSetOp(SetOp op, Node n) { VisitRelOpDefault(op, n); }
/// <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 (var varMap in op.VarMap) { foreach (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 // var 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> // Common copy path for all SetOps // </summary> // <param name="op"> The SetOp to Copy (must be one of ExceptOp, IntersectOp, UnionAllOp) </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> private Node CopySetOp(SetOp op, Node n) { // Visit the Node's children and map their Vars var children = ProcessChildren(n); var leftMap = new VarMap(); var rightMap = new VarMap(); foreach (var kv in op.VarMap[0]) { // Create a new output Var that is a copy of the original output Var Var outputVar = m_destCmd.CreateSetOpVar(kv.Key.Type); // Add a mapping for the new output var we've just created SetMappedVar(kv.Key, outputVar); // Add this output var's entries to the new VarMaps leftMap.Add(outputVar, GetMappedVar(kv.Value)); rightMap.Add(outputVar, GetMappedVar((op.VarMap[1])[kv.Key])); } SetOp newSetOp = null; switch (op.OpType) { case OpType.UnionAll: { var branchDiscriminator = ((UnionAllOp)op).BranchDiscriminator; if (null != branchDiscriminator) { branchDiscriminator = GetMappedVar(branchDiscriminator); } newSetOp = m_destCmd.CreateUnionAllOp(leftMap, rightMap, branchDiscriminator); } break; case OpType.Intersect: { newSetOp = m_destCmd.CreateIntersectOp(leftMap, rightMap); } break; case OpType.Except: { newSetOp = m_destCmd.CreateExceptOp(leftMap, rightMap); } break; default: { Debug.Assert(false, "Unexpected SetOpType"); } break; } return m_destCmd.CreateNode(newSetOp, children); }
protected override void VisitSetOp(SetOp op, Node n) { VisitRelOpDefault(op, n); Map(op.VarMap[0]); Map(op.VarMap[1]); }
protected virtual void VisitSetOp(SetOp op, Node n) { this.VisitRelOpDefault((RelOp)op, n); }
protected override NodeInfo VisitSetOp(SetOp op, Node n) { ExtendedNodeInfo extendedNodeInfo1 = this.InitExtendedNodeInfo(n); extendedNodeInfo1.Definitions.InitFrom(op.Outputs); extendedNodeInfo1.LocalDefinitions.InitFrom(op.Outputs); ExtendedNodeInfo extendedNodeInfo2 = this.GetExtendedNodeInfo(n.Child0); ExtendedNodeInfo extendedNodeInfo3 = this.GetExtendedNodeInfo(n.Child1); RowCount rowCount = RowCount.Zero; extendedNodeInfo1.ExternalReferences.Or(extendedNodeInfo2.ExternalReferences); extendedNodeInfo1.ExternalReferences.Or(extendedNodeInfo3.ExternalReferences); if (op.OpType == OpType.UnionAll) { rowCount = extendedNodeInfo2.MinRows > extendedNodeInfo3.MinRows ? extendedNodeInfo2.MinRows : extendedNodeInfo3.MinRows; } if (op.OpType == OpType.Intersect || op.OpType == OpType.Except) { extendedNodeInfo1.Keys.InitFrom((IEnumerable <Var>)op.Outputs); } else { UnionAllOp unionAllOp = (UnionAllOp)op; if (unionAllOp.BranchDiscriminator == null) { extendedNodeInfo1.Keys.NoKeys = true; } else { VarVec varVec = this.m_command.CreateVarVec(); for (int index = 0; index < n.Children.Count; ++index) { ExtendedNodeInfo extendedNodeInfo4 = n.Children[index].GetExtendedNodeInfo(this.m_command); if (!extendedNodeInfo4.Keys.NoKeys && !extendedNodeInfo4.Keys.KeyVars.IsEmpty) { VarVec other = extendedNodeInfo4.Keys.KeyVars.Remap((Dictionary <Var, Var>)unionAllOp.VarMap[index].GetReverseMap()); varVec.Or(other); } else { varVec.Clear(); break; } } if (varVec.IsEmpty) { extendedNodeInfo1.Keys.NoKeys = true; } else { extendedNodeInfo1.Keys.InitFrom((IEnumerable <Var>)varVec); } } } VarVec other1 = extendedNodeInfo2.NonNullableDefinitions.Remap((Dictionary <Var, Var>)op.VarMap[0].GetReverseMap()); extendedNodeInfo1.NonNullableDefinitions.InitFrom(other1); if (op.OpType != OpType.Except) { VarVec other2 = extendedNodeInfo3.NonNullableDefinitions.Remap((Dictionary <Var, Var>)op.VarMap[1].GetReverseMap()); if (op.OpType == OpType.Intersect) { extendedNodeInfo1.NonNullableDefinitions.Or(other2); } else { extendedNodeInfo1.NonNullableDefinitions.And(other2); } } extendedNodeInfo1.NonNullableDefinitions.And(op.Outputs); extendedNodeInfo1.MinRows = rowCount; return((NodeInfo)extendedNodeInfo1); }
// <summary> // SetOp common processing // </summary> // <remarks> // The input to an IntersectOp or an ExceptOp cannot be a NestOp – that // would imply that we support distinctness over collections - which // we don’t. // UnionAllOp is somewhat trickier. We would need a way to percolate keys // up the UnionAllOp – and I’m ok with not supporting this case for now. // </remarks> protected override Node VisitSetOp(SetOp op, Node n) { return NestingNotSupported(op, n); }
protected override void VisitSetOp(SetOp op, Node n) { VisitRelOpDefault(op, n); AssertRelOpOrPhysicalOp(n.Child0.Op); AssertRelOpOrPhysicalOp(n.Child1.Op); // // Ensure that the corresponding setOp Vars are all of the same // type // foreach (var varMap in op.VarMap) { foreach (var kv in varMap) { AssertEqualTypes(kv.Key.Type, kv.Value.Type); } } }
// <summary> // A default processor for all SetOps. // Allows new visitors to just override this to handle all SetOps. // </summary> // <param name="op"> the SetOp </param> // <param name="n"> the node to process </param> // <returns> a potentially modified subtree </returns> protected virtual TResultType VisitSetOp(SetOp op, Node n) { return(VisitRelOpDefault(op, n)); }