public override void Visit(WBooleanComparisonExpression node) { Attach(node); }
public override void Visit(WBooleanComparisonExpression node) { if (_checkNodeEdgeReferenceVisitor.Invoke(node)) { UpdateWherClause(_nodeEdgePredicatesWhenClause, node); } }
private List<WSqlStatement> Translate(IList<WSqlStatement> statements) { var result = new List<WSqlStatement>(); var index = 0; for (var count = statements.Count; index < count; ++index) { var insertEdgeStatement = statements[index] as WInsertEdgeSpecification; if (insertEdgeStatement != null) { result.Add(new WBeginTransactionStatement { Name = new WIdentifierOrValueExpression { Identifier = new Identifier { Value = "InsertEdgeTran" } } }); //result.Add(TranslateInsertEdge(insertEdgeStatement, false)); //result.Add(TranslateInsertEdge(insertEdgeStatement, true)); TranslateEdgeInsert(insertEdgeStatement,result); result.Add(new WCommitTransactionStatement { Name = new WIdentifierOrValueExpression { Identifier = new Identifier { Value = "InsertEdgeTran" } } }); continue; } var deleteEdgeStatement = statements[index] as WDeleteEdgeSpecification; if (deleteEdgeStatement != null) { result.Add(new WBeginTransactionStatement { Name = new WIdentifierOrValueExpression { Identifier = new Identifier { Value = "DeleteEdgeTran" } } }); //result.Add(TranslateDeleteEdge(deleteEdgeStatement, true)); //result.Add(TranslateDeleteEdge(deleteEdgeStatement, false)); TranslateEdgeDelete(deleteEdgeStatement,result); result.Add(new WCommitTransactionStatement { Name = new WIdentifierOrValueExpression { Identifier = new Identifier { Value = "DeleteEdgeTran" } } }); continue; } var deleteNodeStatement = statements[index] as WDeleteNodeSpecification; if (deleteNodeStatement != null) { var table = deleteNodeStatement.Target as WNamedTableReference; if (table == null) throw new GraphViewException("Target of DELETE NODE statement should be a named table reference."); WBooleanExpression cond = new WBooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new Identifier { Value = "InDegree"}) }, SecondExpr = new WValueExpression { Value = "0" } }; var tableSchema = table.TableObjectName.SchemaIdentifier == null ? "dbo" : table.TableObjectName.SchemaIdentifier.Value; var tableName = table.TableObjectName.BaseIdentifier.Value; using (var command = _conn.CreateCommand()) { command.CommandText = string.Format( @"SELECT [TableSchema], [TableName], [ColumnName] FROM [{3}] WHERE TableSchema = '{0}' and [TableName]='{1}' and ColumnRole={2}", tableSchema, tableName, 1, GraphViewConnection.MetadataTables[1]); using (var reader = command.ExecuteReader()) { while (reader.Read()) { var col = reader["ColumnName"].ToString(); cond = WBooleanBinaryExpression.Conjunction(cond, new WBooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new Identifier { Value = col + "OutDegree" }) }, SecondExpr = new WValueExpression { Value = "0" } }); } } } WWhereClause checkDeleteNode = new WWhereClause { SearchCondition = new WBooleanNotExpression {Expression = cond} }; if (deleteNodeStatement.WhereClause == null || deleteNodeStatement.WhereClause.SearchCondition == null) { deleteNodeStatement.WhereClause = new WWhereClause {SearchCondition = cond}; } else { checkDeleteNode = new WWhereClause { SearchCondition = new WBooleanBinaryExpression { BooleanExpressionType = BooleanBinaryExpressionType.And, FirstExpr = deleteNodeStatement.WhereClause.SearchCondition, SecondExpr = checkDeleteNode.SearchCondition } }; deleteNodeStatement.WhereClause = new WWhereClause { SearchCondition = new WBooleanBinaryExpression { BooleanExpressionType = BooleanBinaryExpressionType.And, FirstExpr = deleteNodeStatement.WhereClause.SearchCondition, SecondExpr = cond } }; } using (var command = _conn.CreateCommand()) { command.CommandText = string.Format("SELECT InDegree FROM {0}.{1} {2}", tableSchema, tableName, checkDeleteNode.ToString()); using (var reader = command.ExecuteReader()) { while (reader.Read()) { throw new GraphViewException( string.Format( "Node(s) of node table {0} being deleted still has/have ingoing or outdoing edge(s)", tableName)); } } } } result.Add(statements[index]); } return result; }
private WBooleanExpression ParseBooleanExpression(BooleanExpression bexpr) { if (bexpr == null) { return null; } switch (bexpr.GetType().Name) { case "BooleanBinaryExpression": { var oexpr = bexpr as BooleanBinaryExpression; var pexpr = new WBooleanBinaryExpression { FirstExpr = ParseBooleanExpression(oexpr.FirstExpression), SecondExpr = ParseBooleanExpression(oexpr.SecondExpression), BooleanExpressionType = oexpr.BinaryExpressionType, FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; return pexpr; } case "BooleanComparisonExpression": { var oexpr = bexpr as BooleanComparisonExpression; var pexpr = new WBooleanComparisonExpression { ComparisonType = oexpr.ComparisonType, FirstExpr = ParseScalarExpression(oexpr.FirstExpression), SecondExpr = ParseScalarExpression(oexpr.SecondExpression), FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; return pexpr; } case "BooleanIsNullExpression": { var oexpr = bexpr as BooleanIsNullExpression; var pexpr = new WBooleanIsNullExpression { IsNot = oexpr.IsNot, Expression = ParseScalarExpression(oexpr.Expression), FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; return pexpr; } case "BooleanNotExpression": { var oexpr = bexpr as BooleanNotExpression; var pexpr = new WBooleanNotExpression { Expression = ParseBooleanExpression(oexpr.Expression), FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; return pexpr; } case "BooleanParenthesisExpression": { var oexpr = bexpr as BooleanParenthesisExpression; var pexpr = new WBooleanParenthesisExpression { Expression = ParseBooleanExpression(oexpr.Expression), FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; return pexpr; } case "BooleanTernaryExpression": { var oexpr = bexpr as BooleanTernaryExpression; var pexpr = new WBetweenExpression { FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; switch (oexpr.TernaryExpressionType) { case BooleanTernaryExpressionType.Between: pexpr.NotDefined = false; break; case BooleanTernaryExpressionType.NotBetween: pexpr.NotDefined = true; break; default: throw new GraphViewException("Undefined tenary expression type"); } pexpr.FirstExpr = ParseScalarExpression(oexpr.FirstExpression); pexpr.SecondExpr = ParseScalarExpression(oexpr.SecondExpression); pexpr.ThirdExpr = ParseScalarExpression(oexpr.ThirdExpression); return pexpr; } case "ExistsPredicate": { var oexpr = bexpr as ExistsPredicate; var pexpr = new WExistsPredicate { FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, Subquery = new WScalarSubquery { SubQueryExpr = ParseSelectQueryStatement(oexpr.Subquery.QueryExpression), FirstTokenIndex = oexpr.Subquery.FirstTokenIndex, LastTokenIndex = oexpr.Subquery.LastTokenIndex, } }; return pexpr; } case "InPredicate": { var oexpr = bexpr as InPredicate; var pexpr = new WInPredicate { Expression = ParseScalarExpression(oexpr.Expression), NotDefined = oexpr.NotDefined, FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; if (oexpr.Subquery != null) { pexpr.Subquery = new WScalarSubquery { SubQueryExpr = ParseSelectQueryStatement(oexpr.Subquery.QueryExpression), FirstTokenIndex = oexpr.Subquery.FirstTokenIndex, LastTokenIndex = oexpr.Subquery.LastTokenIndex, }; } else { pexpr.Values = new List<WScalarExpression>(oexpr.Values.Count); foreach (var wexp in oexpr.Values.Select(ParseScalarExpression).Where(wexp => wexp != null)) { pexpr.Values.Add(wexp); } } return pexpr; } case "LikePredicate": { var oexpr = bexpr as LikePredicate; var pexpr = new WLikePredicate { EscapeExpr = ParseScalarExpression(oexpr.EscapeExpression), FirstExpr = ParseScalarExpression(oexpr.FirstExpression), SecondExpr = ParseScalarExpression(oexpr.SecondExpression), NotDefined = oexpr.NotDefined, FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, }; return pexpr; } case "SubqueryComparisonPredicate": { var oexpr = bexpr as SubqueryComparisonPredicate; var pexpr = new WSubqueryComparisonPredicate { FirstTokenIndex = oexpr.FirstTokenIndex, LastTokenIndex = oexpr.LastTokenIndex, Subquery = new WScalarSubquery() { SubQueryExpr = ParseSelectQueryStatement(oexpr.Subquery.QueryExpression), FirstTokenIndex = oexpr.Subquery.FirstTokenIndex, LastTokenIndex = oexpr.Subquery.LastTokenIndex }, ComparisonType = oexpr.ComparisonType, Expression = ParseScalarExpression(oexpr.Expression), SubqueryComparisonType = oexpr.SubqueryComparisonPredicateType, }; return pexpr; } default: { return null; } } }
/// <summary> /// If a table alias in the MATCH clause is defined in an upper-level context, /// to be able to translate this MATCH clause, this table alias must be re-materialized /// in the FROM clause of the current context and joined with the corresponding table /// in the upper-level context. /// </summary> /// <param name="query">Select query</param> /// <param name="nodes">A collection of node alias and match node instance</param> private void RematerilizeExtrenalNodeTableReference(WSelectQueryBlock query, Dictionary<string, MatchNode> nodes) { var tableRefs = query.FromClause.TableReferences; var tableSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var newTableRefs = new List<WTableReference>(); for (int index = 0; index < tableRefs.Count; ++index) { var table = tableRefs[index] as WNamedTableReference; if (table == null) { newTableRefs.Add(tableRefs[index]); continue; } if (!nodes.ContainsKey(table.ExposedName.Value)) { newTableRefs.Add(table); } else { tableSet.Add(table.ExposedName.Value); } } query.FromClause = new WFromClause { TableReferences = newTableRefs, }; WBooleanExpression whereCondiction = null; foreach (var node in nodes.Where(node => !tableSet.Contains(node.Key))) { node.Value.External = true; var newWhereCondition = new WBooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = node.Key }, new Identifier { Value = "GlobalNodeId" }) }, SecondExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = node.Value.RefAlias }, new Identifier { Value = "GlobalNodeId" }) }, }; whereCondiction = WBooleanBinaryExpression.Conjunction(whereCondiction, newWhereCondition); } if (whereCondiction != null) { if (query.WhereClause == null) { query.WhereClause = new WWhereClause { SearchCondition = whereCondiction }; } else { if (query.WhereClause.SearchCondition == null) { query.WhereClause.SearchCondition = whereCondiction; } else { query.WhereClause.SearchCondition = new WBooleanBinaryExpression { BooleanExpressionType = BooleanBinaryExpressionType.And, FirstExpr = new WBooleanParenthesisExpression { Expression = query.WhereClause.SearchCondition }, SecondExpr = new WBooleanParenthesisExpression { Expression = whereCondiction } }; } } } }
public virtual void Visit(WBooleanComparisonExpression node) { node.AcceptChildren(this); }
private WBooleanExpression ConstructJoinCondition( CandidateJoinUnit candidateTree, IMatchJoinStatisticsCalculator statisticsCalculator, GraphMetaData metaData, out double joinSelectivity, out double sqlEstimatedJoinSelectivity) { joinSelectivity = 1.0; sqlEstimatedJoinSelectivity = 1.0; var root = candidateTree.TreeRoot; WBooleanExpression joinCondition = null; string nodeName = ""; // Update Nodes if (MaterializedNodeSplitCount.ContainsKey(root)) { MaterializedNodeSplitCount[root]++; nodeName = GetNodeRefName(root); joinCondition = new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = root.RefAlias }, new Identifier { Value = "GlobalNodeId" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ), }, ComparisonType = BooleanComparisonType.Equals }; } else { nodeName = root.RefAlias; if (!Nodes.Contains(root)) Nodes.Add(root); MaterializedNodeSplitCount[root] = 0; } List<double> densityList = new List<double>(); List<MatchEdge> inEdges; if (UnmaterializedNodeMapping.TryGetValue(root, out inEdges)) { var firstEdge = inEdges.First(); bool materialized = EdgeMaterilizedDict[firstEdge]; UnmaterializedNodeMapping.Remove(root); joinSelectivity *= 1.0 / root.TableRowCount; // Component materialized edge to root if (materialized) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); densityList.Add(root.GlobalNodeIdDensity); } // Component unmaterialized edge to root else { Statistics statistics = null; foreach (var edge in inEdges) { // Update component table TableRef = SpanTableRef(TableRef, edge, GetNodeRefName(edge.SourceNode),metaData); EdgeMaterilizedDict[edge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = edge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); double selectivity; statistics = Statistics.UpdateHistogram(statistics, edge.Statistics, out selectivity); joinSelectivity *= selectivity; densityList.Add(root.GlobalNodeIdDensity); } SinkNodeStatisticsDict[root] = statistics; } } var jointEdges = candidateTree.MaterializedEdges; foreach (var jointEdge in jointEdges) { EdgeMaterilizedDict[jointEdge] = true; var sinkNode = jointEdge.SinkNode; // Leaf to component materialized node if (MaterializedNodeSplitCount.ContainsKey(sinkNode)) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = sinkNode.RefAlias }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); Statistics sinkNodeStatistics; if (!SinkNodeStatisticsDict.TryGetValue(sinkNode, out sinkNodeStatistics)) { sinkNodeStatistics = null; joinSelectivity *= 1.0 / sinkNode.TableRowCount; } double selectivity; var statistics = Statistics.UpdateHistogram(sinkNodeStatistics, jointEdge.Statistics, out selectivity); joinSelectivity *= selectivity; SinkNodeStatisticsDict[sinkNode] = statistics; densityList.Add(sinkNode.GlobalNodeIdDensity); } // Leaf to component unmaterialized node else { inEdges = UnmaterializedNodeMapping[sinkNode]; var firstEdge = inEdges.First(); bool materlizedEdge = EdgeMaterilizedDict[firstEdge]; // Leaf to materialized leaf if (materlizedEdge) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); densityList.Add(Statistics.DefaultDensity); double selectivity; var statistics = Statistics.UpdateHistogram(SinkNodeStatisticsDict[sinkNode], jointEdge.Statistics, out selectivity); joinSelectivity *= selectivity; SinkNodeStatisticsDict[sinkNode] = statistics; } // Leaf to unmaterialized leaf else { Statistics compSinkNodeStatistics = null; foreach (var inEdge in inEdges) { TableRef = SpanTableRef(TableRef, inEdge, GetNodeRefName(inEdge.SourceNode),metaData); EdgeMaterilizedDict[inEdge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = inEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); densityList.Add(Statistics.DefaultDensity); double selectivity; var leafToLeafStatistics = statisticsCalculator.GetLeafToLeafStatistics(jointEdge, inEdge, out selectivity); joinSelectivity *= selectivity; compSinkNodeStatistics = Statistics.UpdateHistogram(compSinkNodeStatistics, inEdge.Statistics, out selectivity); } SinkNodeStatisticsDict[sinkNode] = compSinkNodeStatistics; } } } var unmatEdges = candidateTree.UnmaterializedEdges; foreach (var unmatEdge in unmatEdges) { EdgeMaterilizedDict[unmatEdge] = false; if (!Nodes.Contains(unmatEdge.SinkNode)) Nodes.Add(unmatEdge.SinkNode); var sinkNodeInEdges = UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode); sinkNodeInEdges.Add(unmatEdge); } // Calculate Estimated Join Selectivity & Estimated Node Size densityList.Sort(); for (int i = densityList.Count - 1; i >= 0; i--) { sqlEstimatedJoinSelectivity *= Math.Sqrt(sqlEstimatedJoinSelectivity) * densityList[i]; } return joinCondition; }
private WBooleanExpression ConstructJoinCondition( CandidateJoinUnit candidateTree, IMatchJoinStatisticsCalculator statisticsCalculator, GraphMetaData metaData, Dictionary<Tuple<string, bool>, Statistics> srcNodeStatisticsDict, out double preJoinSelectivity, out double postJoinSelectivity, out double sqlEstimatedJoinSelectivity) { const double sizeThreshold = 1e8; const int loopJoinFactorThreshold = 20; preJoinSelectivity = 1.0; postJoinSelectivity = 1.0; sqlEstimatedJoinSelectivity = 1.0; var firstJoin = MaterializedNodeSplitCount.Count == 1; MatchNode firstNode = null; if (firstJoin) firstNode = Nodes.First(); var root = candidateTree.TreeRoot; WBooleanExpression joinCondition = null; WBooleanExpression whereCondition = null; string nodeName = root.RefAlias; if (!Nodes.Contains(root)) Nodes.Add(root); MaterializedNodeSplitCount[root] = 0; var inEdges = candidateTree.PreMatIncomingEdges.Select( e => new Tuple<MaterializedOrder, MatchEdge>(MaterializedOrder.Pre, e)) .Union( candidateTree.PostMatIncomingEdges.Select( e => new Tuple<MaterializedOrder, MatchEdge>(MaterializedOrder.Post, e))) .ToList(); var outEdges = candidateTree.PreMatOutgoingEdges.Select( e => new Tuple<MaterializedOrder, MatchEdge>(MaterializedOrder.Pre, e)) .Union( candidateTree.PostMatOutgoingEdges.Select( e => new Tuple<MaterializedOrder, MatchEdge>(MaterializedOrder.Post, e))) .ToList(); var densityList = new List<double>(); var inPostCount = 0; var outPostCount = 0; if (inEdges.Any()) { UnmaterializedNodeMapping.Remove(root); //joinSelectivity *= 1.0 / root.TableRowCount; Statistics statistics = null; Statistics srcNodeStat = null; foreach (var t in inEdges) { var order = t.Item1; var edge = t.Item2; var globalNodeIdRef = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = nodeName}, new Identifier {Value = "GlobalNodeId"} ) }; var newCondition = new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = edge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = order == MaterializedOrder.Post && inPostCount > 0 ? new WBinaryExpression { ExpressionType = BinaryExpressionType.Add, FirstExpr = globalNodeIdRef, SecondExpr = new WValueExpression { SingleQuoted = false, Value = "0", } } : (WScalarExpression)globalNodeIdRef, ComparisonType = BooleanComparisonType.Equals }; EdgeMaterilizedDict[edge] = true; double selectivity; statistics = Statistics.UpdateHistogram(statistics, edge.Statistics, out selectivity); if (order == MaterializedOrder.Pre) { preJoinSelectivity *= selectivity; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, newCondition); } else { ++inPostCount; postJoinSelectivity *= selectivity; whereCondition = WBooleanBinaryExpression.Conjunction(whereCondition, newCondition); } if (firstJoin) { double srcNodeSelectivity; srcNodeStat = Statistics.UpdateHistogram(srcNodeStat, srcNodeStatisticsDict[new Tuple<string, bool>(edge.EdgeAlias, edge.IsReversedEdge)], out srcNodeSelectivity); } densityList.Add(root.GlobalNodeIdDensity); } if (firstJoin) SinkNodeStatisticsDict[firstNode] = srcNodeStat; SinkNodeStatisticsDict[root] = statistics; } if (candidateTree.JoinHint == JoinHint.Loop) { var size = Cardinality*candidateTree.PreMatIncomingEdges.Select(e => e.AverageDegree) .Aggregate(1.0, (cur, next) => cur*next)*preJoinSelectivity; if (size >= sizeThreshold && size > root.EstimatedRows * loopJoinFactorThreshold) candidateTree.JoinHint = JoinHint.Hash; } if (outEdges.Any()) { foreach (var t in outEdges) { var order = t.Item1; var edge = t.Item2; var sinkNode = edge.SinkNode; var globalNodeIdRef = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = sinkNode.RefAlias}, new Identifier {Value = "GlobalNodeId"} ) }; var newCondition = new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = edge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = order == MaterializedOrder.Post && outPostCount > 0 ? new WBinaryExpression { ExpressionType = BinaryExpressionType.Add, FirstExpr = globalNodeIdRef, SecondExpr = new WValueExpression { SingleQuoted = false, Value = "0", } } : (WScalarExpression)globalNodeIdRef, ComparisonType = BooleanComparisonType.Equals }; EdgeMaterilizedDict[edge] = true; Statistics sinkNodeStatistics; if (!SinkNodeStatisticsDict.TryGetValue(sinkNode, out sinkNodeStatistics)) { sinkNodeStatistics = null; //joinSelectivity *= 1.0 / sinkNode.TableRowCount; } double selectivity; var statistics = Statistics.UpdateHistogram(sinkNodeStatistics, edge.Statistics, out selectivity); if (order == MaterializedOrder.Pre) { preJoinSelectivity *= selectivity; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, newCondition); } else { ++outPostCount; postJoinSelectivity *= selectivity; whereCondition = WBooleanBinaryExpression.Conjunction(whereCondition, newCondition); } SinkNodeStatisticsDict[sinkNode] = statistics; densityList.Add(sinkNode.GlobalNodeIdDensity); } } var unmatEdges = candidateTree.UnmaterializedEdges; foreach (var unmatEdge in unmatEdges) { EdgeMaterilizedDict[unmatEdge] = false;; var unmatNodeInEdges = UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode); unmatNodeInEdges.Add(unmatEdge); } densityList.Sort(); for (int i = densityList.Count - 1; i >= 0; i--) { sqlEstimatedJoinSelectivity *= Math.Sqrt(sqlEstimatedJoinSelectivity) * densityList[i]; } WhereCondition = WBooleanBinaryExpression.Conjunction(WhereCondition, whereCondition); return joinCondition; }
private void TranslateNodeDelete(WDeleteNodeSpecification node, List<WSqlStatement> res) { var table = node.Target as WNamedTableReference; if (table == null) throw new GraphViewException("Target of DELETE NODE statement should be a named table reference."); WBooleanExpression cond = new WBooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new Identifier { Value = "InDegree" }) }, SecondExpr = new WValueExpression { Value = "0" } }; var tableSchema = table.TableObjectName.SchemaIdentifier == null ? "dbo" : table.TableObjectName.SchemaIdentifier.Value; var tableName = table.TableObjectName.BaseIdentifier.Value; using (var command = Tx.Connection.CreateCommand()) { command.Transaction = Tx; command.CommandText = string.Format( @"SELECT [TableSchema], [TableName], [ColumnName] FROM [{3}] WHERE TableSchema = '{0}' and [TableName]='{1}' and ColumnRole={2}", tableSchema, tableName, 1, GraphViewConnection.MetadataTables[1]); using (var reader = command.ExecuteReader()) { while (reader.Read()) { var col = reader["ColumnName"].ToString(); cond = WBooleanBinaryExpression.Conjunction(cond, new WBooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new Identifier { Value = col + "OutDegree" }) }, SecondExpr = new WValueExpression { Value = "0" } }); } } } WWhereClause checkDeleteNode = new WWhereClause { SearchCondition = new WBooleanNotExpression { Expression = new WBooleanParenthesisExpression { Expression = cond } } }; if (node.WhereClause == null || node.WhereClause.SearchCondition == null) { node.WhereClause = new WWhereClause { SearchCondition = cond }; } else { checkDeleteNode = new WWhereClause { SearchCondition = new WBooleanBinaryExpression { BooleanExpressionType = BooleanBinaryExpressionType.And, FirstExpr = node.WhereClause.SearchCondition, SecondExpr = checkDeleteNode.SearchCondition } }; node.WhereClause = new WWhereClause { SearchCondition = new WBooleanBinaryExpression { BooleanExpressionType = BooleanBinaryExpressionType.And, FirstExpr = node.WhereClause.SearchCondition, SecondExpr = cond } }; } using (var command = Tx.Connection.CreateCommand()) { command.Transaction = Tx; command.CommandText = string.Format("SELECT InDegree FROM {0}.{1} {2}", tableSchema, tableName, checkDeleteNode.ToString()); using (var reader = command.ExecuteReader()) { while (reader.Read()) { throw new GraphViewException( string.Format( "Node(s) of node table {0} being deleted still has/have ingoing or outdoing edge(s)", tableName)); } } } res.Add(new WDeleteSpecification { FromClause = node.FromClause, Target = node.Target, TopRowFilter = node.TopRowFilter, WhereClause = node.WhereClause, }); }
/// <summary> /// Transit from current component to the new component in the next state given the Node Unit /// </summary> /// <param name="candidateTree"></param> /// <param name="densityDict"></param> /// <param name="subGraph"></param> /// <param name="statisticsCalculator"></param> /// <returns></returns> public MatchComponent GetNextState( OneHeightTree candidateTree, Dictionary<string, double> densityDict, IMatchJoinStatisticsCalculator statisticsCalculator) { var newComponent = new MatchComponent(this); var root = candidateTree.TreeRoot; WBooleanExpression joinCondition = null; string nodeName = ""; // Update Nodes if (newComponent.MaterializedNodeSplitCount.ContainsKey(root)) { newComponent.MaterializedNodeSplitCount[root]++; nodeName = newComponent.GetNodeRefName(root); joinCondition = new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = root.RefAlias}, new Identifier {Value = "GlobalNodeId"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = nodeName}, new Identifier {Value = "GlobalNodeId"} ), }, ComparisonType = BooleanComparisonType.Equals }; } else { nodeName = root.RefAlias; newComponent.Nodes.Add(root); newComponent.MaterializedNodeSplitCount[root] = 0; newComponent.StatisticsDict[root] = new ColumnStatistics {Selectivity = 1.0/root.TableRowCount}; } // Constructs table reference WTableReference nodeTable = new WNamedTableReference { Alias = new Identifier { Value = nodeName }, TableObjectName = root.TableObjectName }; WTableReference compTable = newComponent.TableRef; // Updates join conditions double selectivity = 1.0; double degrees = 1.0; var DensityCount = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase); List<MatchEdge> inEdges; if (newComponent.UnmaterializedNodeMapping.TryGetValue(root, out inEdges)) { var firstEdge = inEdges.First(); bool materialized = newComponent.EdgeMaterilizedDict[firstEdge]; newComponent.UnmaterializedNodeMapping.Remove(root); selectivity *= 1.0/root.TableRowCount; // Component materialized edge to root if (materialized) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = firstEdge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = nodeName}, new Identifier {Value = "GlobalNodeId"} ) }, ComparisonType = BooleanComparisonType.Equals }); //var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[root], // new ColumnStatistics {Selectivity = 1.0/root.TableRowCount}); //selectivity *= statistics.Selectivity; //newComponent.StatisticsDict[root] = statistics; if (DensityCount.ContainsKey(root.TableObjectName.ToString())) DensityCount[root.TableObjectName.ToString()]++; else DensityCount[root.TableObjectName.ToString()] = 1; } // Component unmaterialized edge to root else { ColumnStatistics statistics = null; foreach (var edge in inEdges) { // Update component table compTable = SpanTableRef(compTable, edge, newComponent.GetNodeRefName(edge.SourceNode)); newComponent.EdgeMaterilizedDict[edge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = edge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = nodeName}, new Identifier {Value = "GlobalNodeId"} ) }, ComparisonType = BooleanComparisonType.Equals }); statistics = ColumnStatistics.UpdateHistogram(statistics, newComponent.Context.GetEdgeStatistics(edge)); selectivity *= statistics.Selectivity; } newComponent.StatisticsDict[root] = statistics; if (DensityCount.ContainsKey(root.TableObjectName.ToString())) DensityCount[root.TableObjectName.ToString()]+=inEdges.Count; else DensityCount[root.TableObjectName.ToString()] = inEdges.Count; } } var jointEdges = candidateTree.MaterializedEdges; int sinkToSinkCount = 0; foreach (var jointEdge in jointEdges) { // Update node table nodeTable = SpanTableRef(nodeTable, jointEdge, nodeName); degrees *= jointEdge.AverageDegree; newComponent.EdgeMaterilizedDict[jointEdge] = true; var sinkNode = jointEdge.SinkNode; // Leaf to component materialized node if (newComponent.MaterializedNodeSplitCount.ContainsKey(sinkNode)) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = jointEdge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = sinkNode.RefAlias}, new Identifier {Value = "GlobalNodeId"} ) }, ComparisonType = BooleanComparisonType.Equals }); var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode], newComponent.Context.GetEdgeStatistics(jointEdge)); selectivity *= statistics.Selectivity; newComponent.StatisticsDict[sinkNode] = statistics; if (DensityCount.ContainsKey(sinkNode.TableObjectName.ToString())) DensityCount[sinkNode.TableObjectName.ToString()]++; else DensityCount[sinkNode.TableObjectName.ToString()] = 1; } // Leaf to component unmaterialized node else { inEdges = newComponent.UnmaterializedNodeMapping[sinkNode]; var firstEdge = inEdges.First(); bool materlizedEdge = newComponent.EdgeMaterilizedDict[firstEdge]; // Leaf to materialized leaf if (materlizedEdge) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = jointEdge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias}, new Identifier {Value = "Sink"} ) }, ComparisonType = BooleanComparisonType.Equals }); sinkToSinkCount++; var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode], newComponent.Context.GetEdgeStatistics(jointEdge)); selectivity *= statistics.Selectivity; newComponent.StatisticsDict[sinkNode] = statistics; } // Leaf to unmaterialized leaf else { ColumnStatistics compSinkNodeStatistics = null; foreach (var inEdge in inEdges) { compTable = SpanTableRef(compTable, inEdge, newComponent.GetNodeRefName(inEdge.SourceNode)); newComponent.EdgeMaterilizedDict[inEdge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = inEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); sinkToSinkCount++; var leafToLeafStatistics = statisticsCalculator.GetLeafToLeafStatistics(jointEdge, inEdge); selectivity *= leafToLeafStatistics.Selectivity; compSinkNodeStatistics = ColumnStatistics.UpdateHistogram(compSinkNodeStatistics, newComponent.Context.GetEdgeStatistics(inEdge)); } newComponent.StatisticsDict[sinkNode] = compSinkNodeStatistics; } } } var unmatEdges = candidateTree.UnmaterializedEdges; foreach (var unmatEdge in unmatEdges) { newComponent.EdgeMaterilizedDict[unmatEdge] = false; newComponent.Nodes.Add(unmatEdge.SinkNode); var sinkNodeInEdges = newComponent.UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode); sinkNodeInEdges.Add(unmatEdge); degrees *= unmatEdge.AverageDegree; } // Calculate Estimated Join Selectivity & Estimated Node Size double estimatedSelectity = 1.0; int count = 0; bool sinkJoin = false; foreach (var item in densityDict.Where(e => DensityCount.ContainsKey(e.Key))) { var density = item.Value; var curJoinCount = DensityCount[item.Key]; var curJoinSelectitivy = Math.Pow(density, 2 - Math.Pow(2, 1 - curJoinCount)); if (!sinkJoin && ColumnStatistics.DefaultDensity < density) { var curSinkJoinSelectivity = Math.Pow(ColumnStatistics.DefaultDensity, 2 - Math.Pow(2, 1 - sinkToSinkCount)); estimatedSelectity *= Math.Pow(curSinkJoinSelectivity, Math.Pow(2, -count)); count += sinkToSinkCount; sinkJoin = true; } estimatedSelectity *= Math.Pow(curJoinSelectitivy, Math.Pow(2, -count)); count += curJoinCount; } var estimatedNodeUnitSize = root.EstimatedRows* Math.Pow(1000, candidateTree.MaterializedEdges.Count + candidateTree.UnmaterializedEdges.Count); // Update Table Reference newComponent.TableRef = GetPlanAndUpdateCost(candidateTree, newComponent, nodeTable, compTable, joinCondition, degrees, selectivity, estimatedNodeUnitSize, estimatedSelectity); return newComponent; }
/// <summary> /// Construct Graph from the match clause. The Graph can consist of multiple connected SubGraph. /// Not supported in this version /// </summary> /// <param name="query"></param> /// <returns></returns> private MatchGraph ConstructGraph(WSelectQueryBlock query) { var unionFind = new UnionFind(); if (query.MatchClause == null) return null; var edgeTableReferenceDict = new Dictionary<string, List<string>>(StringComparer.CurrentCultureIgnoreCase); var matchClause = query.MatchClause; var nodes = new Dictionary<string, MatchNode>(StringComparer.CurrentCultureIgnoreCase); var connectedSubGraphs = new List<ConnectedComponent>(); var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.CurrentCultureIgnoreCase); var parent = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase); unionFind.Parent = parent; HashSet<Tuple<string, string>> nodeTypes = new HashSet<Tuple<string, string>>(); //Construct Graph from Match Pattern foreach (var path in matchClause.Paths) { var index = 0; MatchEdge preEdge = null; for (var count = path.PathNodeList.Count; index < count; ++index) { var currentNode = path.PathNodeList[index].Item1; var currentEdge = path.PathNodeList[index].Item2; var currentNodeExposedName = currentNode.BaseIdentifier.Value; var nextNode = index != count - 1 ? path.PathNodeList[index + 1].Item1 : path.Tail; var nextNodeExposedName = nextNode.BaseIdentifier.Value; var node = nodes.GetOrCreate(currentNodeExposedName); if (node.NodeAlias == null) { node.NodeAlias = currentNodeExposedName; node.Neighbors = new List<MatchEdge>(); node.External = false; var nodeTable = _context[currentNodeExposedName] as WNamedTableReference; if (nodeTable != null) { node.TableObjectName = nodeTable.TableObjectName; if (node.TableObjectName.SchemaIdentifier == null) node.TableObjectName.Identifiers.Insert(0, new Identifier { Value = "dbo" }); var nodeTypeTuple = WNamedTableReference.SchemaNameToTuple(node.TableObjectName); if (!nodeTypes.Contains(nodeTypeTuple)) nodeTypes.Add(nodeTypeTuple); } } if (currentEdge.AliasRole == AliasType.Default) { var currentEdgeName = currentEdge.MultiPartIdentifier.Identifiers.Last().Value; if (edgeTableReferenceDict.ContainsKey(currentEdgeName)) { edgeTableReferenceDict[currentEdgeName].Add(currentEdge.Alias); } else { edgeTableReferenceDict.Add(currentEdgeName, new List<string> { currentEdge.Alias }); } } var edge = new MatchEdge { SourceNode = node, EdgeColumn = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier { Identifiers = new List<Identifier> { new Identifier {Value = node.NodeAlias}, currentEdge.MultiPartIdentifier.Identifiers.Last() } } }, EdgeAlias = currentEdge.Alias }; if (preEdge != null) { preEdge.SinkNode = node; } preEdge = edge; if (!parent.ContainsKey(currentNodeExposedName)) parent[currentNodeExposedName] = currentNodeExposedName; if (!parent.ContainsKey(nextNodeExposedName)) parent[nextNodeExposedName] = nextNodeExposedName; unionFind.Union(currentNodeExposedName, nextNodeExposedName); node.Neighbors.Add(edge); _context.AddEdgeReference(currentEdge.Alias, edge.SourceNode.TableObjectName, currentEdge); } var tailExposedName = path.Tail.BaseIdentifier.Value; var tailNode = nodes.GetOrCreate(tailExposedName); if (tailNode.NodeAlias == null) { tailNode.NodeAlias = tailExposedName; tailNode.Neighbors = new List<MatchEdge>(); var nodeTable = _context[tailExposedName] as WNamedTableReference; if (nodeTable != null) { tailNode.TableObjectName = nodeTable.TableObjectName; if (tailNode.TableObjectName.SchemaIdentifier == null) tailNode.TableObjectName.Identifiers.Insert(0, new Identifier { Value = "dbo" }); var nodeTypeTuple = WNamedTableReference.SchemaNameToTuple(tailNode.TableObjectName); if (!nodeTypes.Contains(nodeTypeTuple)) nodeTypes.Add(nodeTypeTuple); } } if (preEdge != null) preEdge.SinkNode = tailNode; } // Put nodes into subgraphs foreach (var node in nodes) { string root = unionFind.Find(node.Key); if (!subGrpahMap.ContainsKey(root)) { var subGraph = new ConnectedComponent(); subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGrpahMap[root] = subGraph; connectedSubGraphs.Add(subGraph); subGraph.IsTailNode[node.Value] = false; } else { var subGraph = subGrpahMap[root]; subGraph.Nodes[node.Key] = node.Value; foreach (var edge in node.Value.Neighbors) { subGraph.Edges[edge.EdgeAlias] = edge; } subGraph.IsTailNode[node.Value] = false; } } // Replace Edge name alias with proper alias in the query var replaceTableRefVisitor = new ReplaceTableRefVisitor(); replaceTableRefVisitor.Invoke(query, edgeTableReferenceDict); // If a table alias in the MATCH clause is defined in an upper-level context, // to be able to translate this MATCH clause, this table alias must be re-materialized // in the FROM clause of the current context and joined with the corresponding table // in the upper-level context. var tableRefs = query.FromClause.TableReferences; var tableSet = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase); var newTableRefs = new List<WTableReference>(); for (int index = 0; index < tableRefs.Count; ++index) { var table = tableRefs[index] as WNamedTableReference; if (table == null) { newTableRefs.Add(tableRefs[index]); continue; } var tableTuple = WNamedTableReference.SchemaNameToTuple(table.TableObjectName); if (!nodeTypes.Contains(tableTuple)) { newTableRefs.Add(table); } else { tableSet.Add(table.ExposedName.Value); } } query.FromClause = new WFromClause { TableReferences = newTableRefs, }; WBooleanExpression whereCondiction = null; foreach (var node in nodes) { if (!tableSet.Contains(node.Key)) { node.Value.External = true; var newWhereCondition = new WBooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = node.Key }, new Identifier { Value = "GlobalNodeId" }) }, SecondExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = node.Value.RefAlias }, new Identifier { Value = "GlobalNodeId" }) }, }; whereCondiction = WBooleanBinaryExpression.Conjunction(whereCondiction, newWhereCondition); } } if (whereCondiction != null) { if (query.WhereClause == null) { query.WhereClause = new WWhereClause { SearchCondition = whereCondiction }; } else { if (query.WhereClause.SearchCondition == null) { query.WhereClause.SearchCondition = whereCondiction; } else { query.WhereClause.SearchCondition = new WBooleanBinaryExpression { BooleanExpressionType = BooleanBinaryExpressionType.And, FirstExpr = new WBooleanParenthesisExpression { Expression = query.WhereClause.SearchCondition }, SecondExpr = new WBooleanParenthesisExpression { Expression = whereCondiction } }; } } } var graph = new MatchGraph { ConnectedSubGraphs = connectedSubGraphs, NodeTypesSet = nodeTypes, }; unionFind.Parent = null; return graph; }
private WBooleanExpression ConstructJoinCondition( CandidateJoinUnit candidateTree, IMatchJoinStatisticsCalculator statisticsCalculator, GraphMetaData metaData, out double joinSelectivity, out double sqlEstimatedJoinSelectivity) { joinSelectivity = 1.0; sqlEstimatedJoinSelectivity = 1.0; var root = candidateTree.TreeRoot; WBooleanExpression joinCondition = null; string nodeName = ""; // Update Nodes if (MaterializedNodeSplitCount.ContainsKey(root)) { MaterializedNodeSplitCount[root]++; nodeName = GetNodeRefName(root); joinCondition = new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = root.RefAlias }, new Identifier { Value = "GlobalNodeId" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ), }, ComparisonType = BooleanComparisonType.Equals }; } else { nodeName = root.RefAlias; if (!Nodes.Contains(root)) { Nodes.Add(root); } MaterializedNodeSplitCount[root] = 0; } List <double> densityList = new List <double>(); List <MatchEdge> inEdges; if (UnmaterializedNodeMapping.TryGetValue(root, out inEdges)) { var firstEdge = inEdges.First(); bool materialized = EdgeMaterilizedDict[firstEdge]; UnmaterializedNodeMapping.Remove(root); joinSelectivity *= 1.0 / root.TableRowCount; // Component materialized edge to root if (materialized) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); densityList.Add(root.GlobalNodeIdDensity); } // Component unmaterialized edge to root else { Statistics statistics = null; foreach (var edge in inEdges) { // Update component table TableRef = SpanTableRef(TableRef, edge, GetNodeRefName(edge.SourceNode), metaData); EdgeMaterilizedDict[edge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = edge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); double selectivity; statistics = Statistics.UpdateHistogram(statistics, edge.Statistics, out selectivity); joinSelectivity *= selectivity; densityList.Add(root.GlobalNodeIdDensity); } SinkNodeStatisticsDict[root] = statistics; } } var jointEdges = candidateTree.MaterializedEdges; foreach (var jointEdge in jointEdges) { EdgeMaterilizedDict[jointEdge] = true; var sinkNode = jointEdge.SinkNode; // Leaf to component materialized node if (MaterializedNodeSplitCount.ContainsKey(sinkNode)) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = sinkNode.RefAlias }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); Statistics sinkNodeStatistics; if (!SinkNodeStatisticsDict.TryGetValue(sinkNode, out sinkNodeStatistics)) { sinkNodeStatistics = null; joinSelectivity *= 1.0 / sinkNode.TableRowCount; } double selectivity; var statistics = Statistics.UpdateHistogram(sinkNodeStatistics, jointEdge.Statistics, out selectivity); joinSelectivity *= selectivity; SinkNodeStatisticsDict[sinkNode] = statistics; densityList.Add(sinkNode.GlobalNodeIdDensity); } // Leaf to component unmaterialized node else { inEdges = UnmaterializedNodeMapping[sinkNode]; var firstEdge = inEdges.First(); bool materlizedEdge = EdgeMaterilizedDict[firstEdge]; // Leaf to materialized leaf if (materlizedEdge) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); densityList.Add(Statistics.DefaultDensity); double selectivity; var statistics = Statistics.UpdateHistogram(SinkNodeStatisticsDict[sinkNode], jointEdge.Statistics, out selectivity); joinSelectivity *= selectivity; SinkNodeStatisticsDict[sinkNode] = statistics; } // Leaf to unmaterialized leaf else { Statistics compSinkNodeStatistics = null; foreach (var inEdge in inEdges) { TableRef = SpanTableRef(TableRef, inEdge, GetNodeRefName(inEdge.SourceNode), metaData); EdgeMaterilizedDict[inEdge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = inEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); densityList.Add(Statistics.DefaultDensity); double selectivity; var leafToLeafStatistics = statisticsCalculator.GetLeafToLeafStatistics(jointEdge, inEdge, out selectivity); joinSelectivity *= selectivity; compSinkNodeStatistics = Statistics.UpdateHistogram(compSinkNodeStatistics, inEdge.Statistics, out selectivity); } SinkNodeStatisticsDict[sinkNode] = compSinkNodeStatistics; } } } var unmatEdges = candidateTree.UnmaterializedEdges; foreach (var unmatEdge in unmatEdges) { EdgeMaterilizedDict[unmatEdge] = false; if (!Nodes.Contains(unmatEdge.SinkNode)) { Nodes.Add(unmatEdge.SinkNode); } var sinkNodeInEdges = UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode); sinkNodeInEdges.Add(unmatEdge); } // Calculate Estimated Join Selectivity & Estimated Node Size densityList.Sort(); for (int i = densityList.Count - 1; i >= 0; i--) { sqlEstimatedJoinSelectivity *= Math.Sqrt(sqlEstimatedJoinSelectivity) * densityList[i]; } return(joinCondition); }
public override void Visit(WBooleanComparisonExpression node) { Extract(node); }