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;
        }
Example #4
0
        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);
 }
Example #7
0
        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;
        }
Example #8
0
        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,
            });
        }
Example #10
0
        /// <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;
        }
Example #12
0
 public virtual void Visit(WBooleanComparisonExpression node)
 {
     node.AcceptChildren(this);
 }
Example #13
0
        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);
 }
 public override void Visit(WBooleanComparisonExpression node)
 {
     Attach(node);
 }