private AlgebraNode PushOverJoin(ComputeScalarAlgebraNode node) { JoinAlgebraNode joinAlgebraNode = (JoinAlgebraNode)node.Input; RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Right); List <ComputedValueDefinition> remainingValueDefinitions = new List <ComputedValueDefinition>(); List <ComputedValueDefinition> leftPushedValueDefinitions = new List <ComputedValueDefinition>(); List <ComputedValueDefinition> rightPushedValueDefinitions = new List <ComputedValueDefinition>(); bool canPushToLeftSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; bool canPushToRightSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; foreach (ComputedValueDefinition valueDefinition in node.DefinedValues) { RowBufferEntry[] referencedValues = AstUtil.GetRowBufferEntryReferences(valueDefinition.Expression); bool referencesProbeColumn = ArrayHelpers.Contains(referencedValues, joinAlgebraNode.ProbeBufferEntry); if (!referencesProbeColumn && canPushToLeftSide && AstUtil.DoesNotReference(referencedValues, rightDefinedValues)) { leftPushedValueDefinitions.Add(valueDefinition); } else if (!referencesProbeColumn && canPushToRightSide && AstUtil.DoesNotReference(referencedValues, leftDefinedValues)) { rightPushedValueDefinitions.Add(valueDefinition); } else { remainingValueDefinitions.Add(valueDefinition); } } if (leftPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = leftPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Left; joinAlgebraNode.Left = VisitAlgebraNode(computeScalarAlgebraNode); } if (rightPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = rightPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Right; joinAlgebraNode.Right = VisitAlgebraNode(computeScalarAlgebraNode); } if (remainingValueDefinitions.Count == 0) { return(joinAlgebraNode); } node.DefinedValues = remainingValueDefinitions.ToArray(); return(node); }
////REVIEW: given that the PlayerConnection will connect to the editor regardless, we end up //// on this path whether input remoting is enabled or not private void OnConnected(int id) { if (m_ConnectedIds != null && ArrayHelpers.Contains(m_ConnectedIds, id)) return; ArrayHelpers.Append(ref m_ConnectedIds, id); SendToSubscribers(InputRemoting.MessageType.Connect, new MessageEventArgs {playerId = id}); }
private void OnDisconnected(int id) { if (m_ConnectedIds == null || !ArrayHelpers.Contains(m_ConnectedIds, id)) return; ArrayHelpers.Erase(ref m_ConnectedIds, id); SendToSubscribers(InputRemoting.MessageType.Disconnect, new MessageEventArgs {playerId = id}); }
public override ExpressionNode VisitColumnExpression(ColumnExpression expression) { if (!ArrayHelpers.Contains(_groupedTableRefs, expression.Column.TableRefBinding)) { // The column's table does not belong to the grouped table list. // Therfore it is an ungrouped column. _ungroupedColumnList.Add(expression.Column); } return(base.VisitColumnExpression(expression)); }
public static bool DoesNotReference(RowBufferEntry[] rowBufferEntryReferences, RowBufferEntry[] rowBufferEntries) { foreach (RowBufferEntry rowBufferColumnDependency in rowBufferEntryReferences) { if (ArrayHelpers.Contains(rowBufferEntries, rowBufferColumnDependency)) { return(false); } } return(true); }
private bool IsOuterReference(RowBufferEntry entry) { foreach (RowBufferEntry[] outerReferences in _outerReferences) { if (ArrayHelpers.Contains(outerReferences, entry)) { return(true); } } return(false); }
private static bool AndPartHasOuterReference(ExpressionNode andPart, RowBufferEntry[] definedValues) { RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart); foreach (RowBufferEntry rowBufferEntry in rowBufferEntries) { if (!ArrayHelpers.Contains(definedValues, rowBufferEntry)) { return(true); } } return(false); }
private bool CheckIfNodeHasDependenciesToOuterReferences(AlgebraNode node) { foreach (RowBufferEntry rowBufferEntryReference in AstUtil.GetRowBufferEntryReferences(node)) { foreach (RowBufferEntry[] outerReferences in _outerReferences) { if (ArrayHelpers.Contains(outerReferences, rowBufferEntryReference)) { return(true); } } } return(false); }
public static bool ConversionNeeded(Type fromType, Type targetType) { if (fromType == targetType) { return(false); } // NULL does not need any conversion. if (fromType == typeof(DBNull) || targetType == typeof(DBNull)) { return(false); } // Check if fromType is derived from targetType. In this // case no conversion is needed. Type baseType = fromType.BaseType; while (baseType != null) { if (baseType == targetType) { return(false); } baseType = baseType.BaseType; } if (fromType.IsInterface && targetType == typeof(object)) { // Though interfaces are not derived from System.Object, they are // compatible to it. return(false); } if (targetType.IsInterface) { // Check if fromType implements targetType. In this // case no conversion is needed. if (ArrayHelpers.Contains(fromType.GetInterfaces(), targetType)) { return(false); } } return(true); }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { if (expression.Op == BinaryOperator.LogicalAnd) { return(base.VisitBinaryExpression(expression)); } else if (expression.Op == BinaryOperator.Equal) { RowBufferEntry[] leftRowBufferEntries = AstUtil.GetRowBufferEntryReferences(expression.Left); RowBufferEntry[] rightRowBufferEntries = AstUtil.GetRowBufferEntryReferences(expression.Right); if (leftRowBufferEntries.Length == 1 && rightRowBufferEntries.Length == 1) { RowBufferEntry leftRowBufferEntry = leftRowBufferEntries[0]; RowBufferEntry rightRowBufferEntry = rightRowBufferEntries[0]; if (leftRowBufferEntry != rightRowBufferEntry) { // Both expressions depend on extactly one row buffer entry but // they are not refering to the same row buffer entry. bool leftDependsOnLeft = ArrayHelpers.Contains(_leftDefinedEntries, leftRowBufferEntry); bool rightDependsOnRight = ArrayHelpers.Contains(_rightDefinedEntries, rightRowBufferEntry); bool leftDependsOnRight = ArrayHelpers.Contains(_rightDefinedEntries, leftRowBufferEntry); bool rightDependsOnLeft = ArrayHelpers.Contains(_leftDefinedEntries, rightRowBufferEntry); if (leftDependsOnRight && rightDependsOnLeft) { ExpressionNode oldLeft = expression.Left; expression.Left = expression.Right; expression.Right = oldLeft; leftDependsOnLeft = true; rightDependsOnRight = true; } if (leftDependsOnLeft && rightDependsOnRight) { _equalPredicates.Add(expression); return(LiteralExpression.FromBoolean(true)); } } } } return(expression); }
private AlgebraNode PushOverValueDefininingUnary(IEnumerable <ValueDefinition> definedValues, FilterAlgebraNode node) { UnaryAlgebraNode inputNode = (UnaryAlgebraNode)node.Input; List <ExpressionNode> nonDependingAndParts = new List <ExpressionNode>(); List <ExpressionNode> dependingAndParts = new List <ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart); bool dependsOnDefinedValue = false; foreach (ValueDefinition definedValue in definedValues) { if (ArrayHelpers.Contains(rowBufferEntries, definedValue.Target)) { dependsOnDefinedValue = true; break; } } if (dependsOnDefinedValue) { dependingAndParts.Add(andPart); } else { nonDependingAndParts.Add(andPart); } } if (nonDependingAndParts.Count > 0) { node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, dependingAndParts); inputNode.Input = GetFilterFromAndParts(nonDependingAndParts, inputNode.Input); if (node.Predicate == null) { node.Input = inputNode.Input; inputNode.Input = VisitAlgebraNode(node); return(inputNode); } } node.Input = VisitAlgebraNode(node.Input); return(node); }
private static IteratorOutput[] GetIteratorOutput(int offset, RowBufferEntry[] allEntries, RowBufferEntry[] neededEntries) { List <IteratorOutput> result = new List <IteratorOutput>(neededEntries.Length); for (int i = 0; i < allEntries.Length; i++) { if (ArrayHelpers.Contains(neededEntries, allEntries[i])) { IteratorOutput iteratorOutput = new IteratorOutput(); iteratorOutput.SourceIndex = i; iteratorOutput.TargetIndex = offset + result.Count; result.Add(iteratorOutput); } } return(result.ToArray()); }
public static RowBufferEntry[] GetOuterReferences(JoinAlgebraNode node) { RowBufferEntry[] leftDefinedValues = GetDefinedValueEntries(node.Left); RowBufferEntry[] rowBufferEntries = GetRowBufferEntryReferences(node.Right); List <RowBufferEntry> outerReferenceList = new List <RowBufferEntry>(); foreach (RowBufferEntry rightColumnDependency in rowBufferEntries) { if (ArrayHelpers.Contains(leftDefinedValues, rightColumnDependency)) { outerReferenceList.Add(rightColumnDependency); } } return(outerReferenceList.ToArray()); }
public static bool JoinDoesNotDependOn(JoinAlgebraNode joinNode, AlgebraNode joinSide) { RowBufferEntry[] joinSideDefinedValues = GetDefinedValueEntries(joinSide); if (joinNode.Predicate != null) { RowBufferEntry[] referencedRowBufferEntries = GetRowBufferEntryReferences(joinNode.Predicate); foreach (RowBufferEntry joinSideDefinedValue in joinSideDefinedValues) { if (ArrayHelpers.Contains(referencedRowBufferEntries, joinSideDefinedValue)) { return(false); } } } return(true); }
private void PushOuterReferences(object[] rowBuffer, JoinAlgebraNode node) { if (node.OuterReferences != null && node.OuterReferences.Length > 0) { // Important: We cannot use node.OuterReferences as argument for BoundRowBufferEntrySet(). // The replacment strategy below will replace occurences to the entries by their index // within the array. Therefore we need an array with the same layout as the row buffer. RowBufferEntry[] outerReferences = new RowBufferEntry[node.Left.OutputList.Length]; for (int i = 0; i < outerReferences.Length; i++) { if (ArrayHelpers.Contains(node.OuterReferences, node.Left.OutputList[i])) { outerReferences[i] = node.Left.OutputList[i]; } } BoundRowBufferEntrySet bufferEntrySet = new BoundRowBufferEntrySet(rowBuffer, outerReferences); _outerReferenceStack.Push(bufferEntrySet); } }
public override AlgebraNode VisitConcatAlgebraNode(ConcatAlgebraNode node) { base.VisitConcatAlgebraNode(node); List <AlgebraNode> nonEmptyInputs = new List <AlgebraNode>(); foreach (AlgebraNode input in node.Inputs) { if (input is NullScanAlgebraNode) { // removed by not adding to list. } else { nonEmptyInputs.Add(input); } } if (nonEmptyInputs.Count == 0) { return(CreateNullScan(node.OutputList)); } if (nonEmptyInputs.Count == 1) { int inputIndex = Array.IndexOf(node.Inputs, nonEmptyInputs[0]); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = nonEmptyInputs[0]; foreach (UnitedValueDefinition unitedValueDefinition in node.DefinedValues) { ComputedValueDefinition computedValueDefinition = new ComputedValueDefinition(); computedValueDefinition.Target = unitedValueDefinition.Target; computedValueDefinition.Expression = new RowBufferEntryExpression(unitedValueDefinition.DependendEntries[inputIndex]); definedValues.Add(computedValueDefinition); } computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); computeScalarAlgebraNode.OutputList = node.OutputList; return(computeScalarAlgebraNode); } node.Inputs = nonEmptyInputs.ToArray(); // Update dependend entries for (int i = 0; i < node.DefinedValues.Length; i++) { UnitedValueDefinition definition = node.DefinedValues[i]; List <RowBufferEntry> dependendEntries = new List <RowBufferEntry>(); foreach (RowBufferEntry dependendEntry in definition.DependendEntries) { bool entryInAnyInput = false; foreach (AlgebraNode input in node.Inputs) { if (ArrayHelpers.Contains(input.OutputList, dependendEntry)) { entryInAnyInput = true; break; } } if (entryInAnyInput) { dependendEntries.Add(dependendEntry); } } definition.DependendEntries = dependendEntries.ToArray(); } return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Get declared tables of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right); // Replace outer joins by left-/right-/inner joins if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { if (IsAnyNullRejected(leftDefinedValues)) { if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin) { node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; } else { node.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; } } } if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { if (IsAnyNullRejected(rightDefinedValues)) { if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin) { node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; } else { node.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin; } } } // After converting an outer join to an inner one we can // sometimes eliminate the whole join. if (node.Op == JoinAlgebraNode.JoinOperator.InnerJoin) { // TODO: There is a problem. If the constant scan defines values this does not work. Acutally, // this is currently no problem as the only way to create such a plan is using derived // tables and in this phase the child will be a ResultNode. if (node.Left is ConstantScanAlgebraNode) { return(VisitAlgebraNode(WrapWithFilter(node.Right, node.Predicate))); } if (node.Right is ConstantScanAlgebraNode) { return(VisitAlgebraNode(WrapWithFilter(node.Left, node.Predicate))); } } // Analyze AND-parts of Condition if (node.Predicate == null) { // TODO: This does not work as the children are not yet rearranged. if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin) { bool hasOuterReferences = AstUtil.GetOuterReferences(node).Length == 0; if (!hasOuterReferences) { if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin && AstUtil.WillProduceAtLeastOneRow(node.Right) || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin && AstUtil.WillProduceAtLeastOneRow(node.Left)) { node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; return(VisitAlgebraNode(node)); } } } } else { foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { if (node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin) { // Check if we can derive from this AND-part that a table it depends on // is null-rejected. RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart); foreach (RowBufferEntry rowBufferEntry in rowBufferEntries) { if (AstUtil.ExpressionYieldsNullOrFalseIfRowBufferEntryNull(andPart, rowBufferEntry)) { if (ArrayHelpers.Contains(leftDefinedValues, rowBufferEntry) && node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin) { AddNullRejectedTable(rowBufferEntry); } else if (ArrayHelpers.Contains(rightDefinedValues, rowBufferEntry) && node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin) { AddNullRejectedTable(rowBufferEntry); } } } } } } // Visit children node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return(node); }
private AlgebraNode PushOverJoin(FilterAlgebraNode node) { JoinAlgebraNode inputNode = (JoinAlgebraNode)node.Input; // Get declared tables of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(inputNode.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(inputNode.Right); // Obviously, we cannot merge the filter with the join if the join is an outer join // (since it would change the join's semantics). // // Another less obvious restriction is that we cannot merge a filter with the join if // the join has a passthru predicate. In case the passthru predicte evaluates to true // the filter would not be applied. However, we are allowed to push the filter the over // join. bool canMerge = inputNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin && inputNode.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && inputNode.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && inputNode.PassthruPredicate == null; if (canMerge) { // We can merge the filter with the condition of the join. // // However, we have to make sure that the predicate does not reference the probe column. // Since not having a probe column is the most common case, we don't always split the // predicate into conjuncts. if (inputNode.ProbeBufferEntry == null || !ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(node.Predicate), inputNode.ProbeBufferEntry)) { // Either there is no probe column defined or the filter does not reference it. That means // no splitting necessary, we can just merge the whole predicate with the join predicate. inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, node.Predicate); return(VisitAlgebraNode(inputNode)); } else { // Unfortunately, the filter references the probe column. Now let's check whether we can merge // conjuncts of the predicate. List <ExpressionNode> remainingAndParts = new List <ExpressionNode>(); List <ExpressionNode> mergableAndParts = new List <ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { bool andPartReferencesProbeColumn = ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(andPart), inputNode.ProbeBufferEntry); if (andPartReferencesProbeColumn) { remainingAndParts.Add(andPart); } else { mergableAndParts.Add(andPart); } } if (mergableAndParts.Count > 0) { ExpressionNode combinedMergableAndParts = AstUtil.CombineConditions(LogicalOperator.And, mergableAndParts.ToArray()); inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, combinedMergableAndParts); node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (node.Predicate == null) { return(VisitAlgebraNode(inputNode)); } } } } else { // The condition cannot be merged. Now we try to push AND-parts over the join. List <ExpressionNode> leftAndParts = new List <ExpressionNode>(); List <ExpressionNode> rightAndParts = new List <ExpressionNode>(); List <ExpressionNode> remainingAndParts = new List <ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { bool andPartReferencesProbeColumn = inputNode.ProbeBufferEntry != null && ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(andPart), inputNode.ProbeBufferEntry); if (!andPartReferencesProbeColumn && AstUtil.AllowsLeftPushOver(inputNode.Op) && AstUtil.ExpressionDoesNotReference(andPart, rightDefinedValues)) { // The AND-part depends only on the LHS and the join is inner/left. // So we are allowed to push this AND-part down. leftAndParts.Add(andPart); } else if (!andPartReferencesProbeColumn && AstUtil.AllowsRightPushOver(inputNode.Op) && AstUtil.ExpressionDoesNotReference(andPart, leftDefinedValues)) { // The AND-part depends only on the RHS and the join is inner/right. // So we are allowed to push this AND-part down. rightAndParts.Add(andPart); } else { remainingAndParts.Add(andPart); } } if (leftAndParts.Count > 0) { inputNode.Left = GetFilterFromAndParts(leftAndParts, inputNode.Left); } if (rightAndParts.Count > 0) { inputNode.Right = GetFilterFromAndParts(rightAndParts, inputNode.Right); } node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (node.Predicate == null) { return(VisitAlgebraNode(inputNode)); } } node.Input = VisitAlgebraNode(node.Input); return(node); }