示例#1
0
 private List <string> PopulateAdjacencyListProperties(MatchEdge edge)
 {
     if (edge.EdgeType == WEdgeType.BothEdge)
     {
         return new List <string> {
                    GremlinKeyword.EdgeAdj, GremlinKeyword.ReverseEdgeAdj
         }
     }
     ;
     //
     // IsTraversalThroughPhysicalReverseEdge
     //
     if ((edge.EdgeType == WEdgeType.OutEdge && edge.IsReversed) ||
         edge.EdgeType == WEdgeType.InEdge && !edge.IsReversed)
     {
         return new List <string> {
                    GremlinKeyword.ReverseEdgeAdj
         }
     }
     ;
     else
     {
         return new List <string> {
                    GremlinKeyword.EdgeAdj
         }
     };
 }
示例#2
0
 private static WColumnReferenceExpression GetNodeColumnReferenceExprFromLink(CompileLink link)
 {
     if (link is MatchEdge)
     {
         MatchEdge edge = link as MatchEdge;
         if (edge.EdgeType == WEdgeType.OutEdge)
         {
             return(SqlUtil.GetColumnReferenceExpr(edge.LinkAlias,
                                                   edge.IsReversed ? GremlinKeyword.EdgeSinkV : GremlinKeyword.EdgeSourceV));
         }
         else if (edge.EdgeType == WEdgeType.InEdge)
         {
             return(SqlUtil.GetColumnReferenceExpr(edge.LinkAlias,
                                                   edge.IsReversed ? GremlinKeyword.EdgeSourceV : GremlinKeyword.EdgeSinkV));
         }
         else
         {
             return(SqlUtil.GetColumnReferenceExpr(edge.LinkAlias, GremlinKeyword.EdgeOtherV));
         }
     }
     else if (link is PredicateLink)
     {
         PredicateLink predicateLink = link as PredicateLink;
         if (predicateLink.BooleanExpression is WEdgeVertexBridgeExpression)
         {
             return((predicateLink.BooleanExpression as WEdgeVertexBridgeExpression).FirstExpr as WColumnReferenceExpression);
         }
     }
     throw new QueryCompilationException("Cannot support " + link + " as a traversal link or an edge");
 }
示例#3
0
        /// <summary>
        /// Generate the Table-Valued Function by the edge given the node alias
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="nodeAlias"></param>
        /// <returns></returns>
        private static WTableReference EdgeToTableReference(MatchEdge edge, string nodeAlias)
        {
            var edgeColumn      = edge.EdgeColumn;
            var edgeIdentifiers = edge.EdgeColumn.MultiPartIdentifier.Identifiers;

            if (nodeAlias != edgeIdentifiers.First().Value)
            {
                var identifiers = new List <Identifier>(edgeIdentifiers);
                identifiers.RemoveAt(0);
                identifiers.Insert(0, new Identifier
                {
                    Value = nodeAlias
                });
                edgeColumn = new WColumnReferenceExpression
                {
                    MultiPartIdentifier = new WMultiPartIdentifier
                    {
                        Identifiers = identifiers
                    }
                };
            }
            var columnName       = edgeIdentifiers.Last().Value;
            var deColIdentifiers = new Identifier[]
            {
                edgeColumn.MultiPartIdentifier.Identifiers.First(),
                new Identifier {
                    Value = columnName + "DeleteCol"
                }
            };
            var decoderFunction = new Identifier
            {
                Value = edge.SourceNode.TableObjectName.SchemaIdentifier.Value + '_' +
                        edge.SourceNode.TableObjectName.BaseIdentifier.Value + '_' +
                        columnName + '_' +
                        "Decoder",
            };
            var tableRef = new WSchemaObjectFunctionTableReference
            {
                SchemaObject = new WSchemaObjectName(
                    new Identifier {
                    Value = "dbo"
                },
                    decoderFunction),
                Parameters = new List <WScalarExpression>
                {
                    edgeColumn,
                    new WColumnReferenceExpression
                    {
                        MultiPartIdentifier = new WMultiPartIdentifier(deColIdentifiers)
                    }
                },
                Alias = new Identifier
                {
                    Value = edge.EdgeAlias,
                }
            };

            return(tableRef);
        }
示例#4
0
 /// <summary>
 /// Span the table given the edge using cross apply
 /// </summary>
 /// <param name="tableRef"></param>
 /// <param name="edge"></param>
 /// <param name="nodeAlias"></param>
 /// <returns></returns>
 public static WTableReference SpanTableRef(WTableReference tableRef, MatchEdge edge, string nodeAlias)
 {
     tableRef = new WUnqualifiedJoin
     {
         FirstTableRef       = tableRef,
         SecondTableRef      = EdgeToTableReference(edge, nodeAlias),
         UnqualifiedJoinType = UnqualifiedJoinType.CrossApply,
     };
     return(tableRef);
 }
示例#5
0
 /// <summary>
 /// Span the table given the edge using cross apply
 /// </summary>
 /// <param name="tableRef"></param>
 /// <param name="edge"></param>
 /// <param name="nodeAlias"></param>
 /// <returns></returns>
 public WTableReference SpanTableRef(WTableReference tableRef, MatchEdge edge, string nodeAlias, GraphMetaData metaData)
 {
     tableRef = new WUnqualifiedJoin
     {
         FirstTableRef       = tableRef,
         SecondTableRef      = edge.ToSchemaObjectFunction(nodeAlias, metaData),
         UnqualifiedJoinType = UnqualifiedJoinType.CrossApply,
     };
     return(tableRef);
 }
示例#6
0
 public bool TryGetEdge(string key, out MatchEdge edge)
 {
     foreach (var subGraph in ConnectedSubGraphs)
     {
         if (subGraph.Edges.TryGetValue(key, out edge))
         {
             return(true);
         }
     }
     edge = null;
     return(false);
 }
示例#7
0
        public void AddEdgeReference(MatchEdge edge)
        {
            var edgeAlias = edge.EdgeAlias;

            if (_nodeTableDictionary.ContainsKey(edgeAlias) || _edgeDictionary.ContainsKey(edgeAlias))
            {
                throw new GraphViewException("Duplicate Alias");
            }
            _edgeDictionary.Add(edgeAlias,
                                new Tuple <WSchemaObjectName, WColumnReferenceExpression>(edge.SourceNode.NodeTableObjectName,
                                                                                          edge.EdgeColumn));
        }
示例#8
0
        public ColumnStatistics GetLeafToLeafStatistics(MatchEdge nodeEdge, MatchEdge componentEdge)
        {
            var edgeTuple = new Tuple <string, string>(nodeEdge.EdgeAlias, componentEdge.EdgeAlias);

            if (LeafToLeafSelectivity.ContainsKey(edgeTuple))
            {
                return(LeafToLeafSelectivity[edgeTuple]);
            }

            var mergedStatistics = ColumnStatistics.UpdateHistogram(Context.GetEdgeStatistics(nodeEdge), Context.GetEdgeStatistics(componentEdge));

            LeafToLeafSelectivity[edgeTuple] = mergedStatistics;
            return(mergedStatistics);
        }
        public Statistics GetLeafToLeafStatistics(MatchEdge nodeEdge, MatchEdge componentEdge, out double selectivity)
        {
            var edgeTuple = new Tuple <string, string>(nodeEdge.EdgeAlias, componentEdge.EdgeAlias);
            Tuple <Statistics, double> edgeStatisticsTuple;

            if (_leafToLeafStatistics.TryGetValue(edgeTuple, out edgeStatisticsTuple))
            {
                selectivity = edgeStatisticsTuple.Item2;
                return(edgeStatisticsTuple.Item1);
            }

            var mergedStatistics = Statistics.UpdateHistogram(nodeEdge.Statistics, componentEdge.Statistics,
                                                              out selectivity);

            _leafToLeafStatistics[edgeTuple] = new Tuple <Statistics, double>(mergedStatistics, selectivity);
            return(mergedStatistics);
        }
        /// <summary>
        /// Constructs the graph pattern specified by the MATCH clause. 
        /// The graph pattern may consist of multiple fully-connected sub-graphs.
        /// </summary>
        /// <param name="query">The SELECT query block</param>
        /// <returns>A graph object contains all the connected componeents</returns>
        private MatchGraph ConstructGraph(WSelectQueryBlock query)
        {
            if (query == null || query.MatchClause == null)
                return null;

            var unionFind = new UnionFind();
            var edgeColumnToAliasesDict = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
            var pathDictionary = new Dictionary<string, MatchPath>(StringComparer.OrdinalIgnoreCase);
            var matchClause = query.MatchClause;
            var nodes = new Dictionary<string, MatchNode>(StringComparer.OrdinalIgnoreCase);
            var connectedSubGraphs = new List<ConnectedComponent>();
            var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase);
            var parent = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            unionFind.Parent = parent;

            // Constructs the graph pattern specified by the path expressions in the MATCH clause
            foreach (var path in matchClause.Paths)
            {
                var index = 0;
                MatchEdge preEdge = null;
                for (var count = path.PathEdgeList.Count; index < count; ++index)
                {
                    var currentNodeTableRef = path.PathEdgeList[index].Item1;
                    var currentEdgeColumnRef = path.PathEdgeList[index].Item2;
                    var currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value;
                    var nextNodeTableRef = index != count - 1
                        ? path.PathEdgeList[index + 1].Item1
                        : path.Tail;
                    var nextNodeExposedName = nextNodeTableRef.BaseIdentifier.Value;
                    var patternNode = nodes.GetOrCreate(currentNodeExposedName);
                    if (patternNode.NodeAlias == null)
                    {
                        patternNode.NodeAlias = currentNodeExposedName;
                        patternNode.Neighbors = new List<MatchEdge>();
                        patternNode.External = false;
                        var nodeTable = _context[currentNodeExposedName] as WNamedTableReference;
                        if (nodeTable != null)
                        {
                            patternNode.NodeTableObjectName = nodeTable.TableObjectName;
                            if (patternNode.NodeTableObjectName.SchemaIdentifier == null)
                                patternNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                        }
                    }

                    string edgeAlias = currentEdgeColumnRef.Alias;
                    if (edgeAlias == null)
                    {
                        var currentEdgeName = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value;
                        edgeAlias = string.Format("{0}_{1}_{2}", currentNodeExposedName, currentEdgeName,
                            nextNodeExposedName);
                        if (edgeColumnToAliasesDict.ContainsKey(currentEdgeName))
                        {
                            edgeColumnToAliasesDict[currentEdgeName].Add(edgeAlias);
                        }
                        else
                        {
                            edgeColumnToAliasesDict.Add(currentEdgeName, new List<string> { edgeAlias });
                        }
                    }

                    Identifier edgeIdentifier = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last();
                    string schema = patternNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower();
                    string nodeTableName = patternNode.NodeTableObjectName.BaseIdentifier.Value;
                    string bindTableName =
                        _context.EdgeNodeBinding[
                            new Tuple<string, string>(nodeTableName.ToLower(), edgeIdentifier.Value.ToLower())].ToLower();
                    MatchEdge edge;
                    if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1)
                    {
                        edge = new MatchEdge
                        {
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName =
                                new WSchemaObjectName(
                                    new Identifier {Value = schema},
                                    new Identifier {Value = bindTableName}
                                    ),
                        };
                        _context.AddEdgeReference(edge);
                    }
                    else
                    {
                        MatchPath matchPath = new MatchPath
                        {
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName =
                                new WSchemaObjectName(
                                    new Identifier {Value = schema},
                                    new Identifier {Value = bindTableName}
                                    ),
                            MinLength = currentEdgeColumnRef.MinLength,
                            MaxLength = currentEdgeColumnRef.MaxLength,
                            ReferencePathInfo = false,
                            AttributeValueDict = currentEdgeColumnRef.AttributeValueDict
                        };
                        _context.AddEdgeReference(matchPath);
                        pathDictionary[edgeAlias] = matchPath;
                        edge = matchPath;
                    }

                    if (preEdge != null)
                    {
                        preEdge.SinkNode = patternNode;
                    }
                    preEdge = edge;

                    if (!parent.ContainsKey(currentNodeExposedName))
                        parent[currentNodeExposedName] = currentNodeExposedName;
                    if (!parent.ContainsKey(nextNodeExposedName))
                        parent[nextNodeExposedName] = nextNodeExposedName;

                    unionFind.Union(currentNodeExposedName, nextNodeExposedName);


                    patternNode.Neighbors.Add(edge);


                }
                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.NodeTableObjectName = nodeTable.TableObjectName;
                        if (tailNode.NodeTableObjectName.SchemaIdentifier == null)
                            tailNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                    }
                }
                if (preEdge != null)
                    preEdge.SinkNode = tailNode;
            }

            // Puts 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;
                }
            }

            var graph = new MatchGraph
            {
                ConnectedSubGraphs = connectedSubGraphs,
            };
            unionFind.Parent = null;

            // When an edge in the MATCH clause is not associated with an alias, 
            // assigns to it a default alias: sourceAlias_EdgeColumnName_sinkAlias. 
            // Also rewrites edge attributes anywhere in the query that can be bound to this default alias. 
            var replaceTableRefVisitor = new ReplaceEdgeReferenceVisitor();
            replaceTableRefVisitor.Invoke(query, edgeColumnToAliasesDict);

            // Rematerializes node tables in the MATCH clause which are defined in the upper-level context
            // and join them with the upper-level table references.
            RematerilizeExtrenalNodeTableReference(query, nodes);

            // Transforms the path reference in the SELECT elements into a 
            // scalar function to display path information.
            TransformPathInfoDisplaySelectElement(query, pathDictionary);

            
            return graph;
        }
        /// <summary>
        /// Constructs the graph pattern specified by the MATCH clause. 
        /// The graph pattern may consist of multiple fully-connected sub-graphs.
        /// </summary>
        /// <param name="query">The SELECT query block</param>
        /// <returns>A graph object contains all the connected componeents</returns>
        private MatchGraph ConstructGraph(WSelectQueryBlock query)
        {
            if (query == null || query.MatchClause == null)
                return null;

            var columnsOfNodeTables = _graphMetaData.ColumnsOfNodeTables;
            var nodeViewMapping = _graphMetaData.NodeViewMapping;
            var unionFind = new UnionFind();
            var edgeColumnToAliasesDict = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
            var pathDictionary = new Dictionary<string, MatchPath>(StringComparer.OrdinalIgnoreCase);
            var reversedEdgeDict = new Dictionary<string, MatchEdge>();
            var matchClause = query.MatchClause;
            var nodes = new Dictionary<string, MatchNode>(StringComparer.OrdinalIgnoreCase);
            var connectedSubGraphs = new List<ConnectedComponent>();
            var subGrpahMap = new Dictionary<string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase);
            var parent = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            unionFind.Parent = parent;

            // Constructs the graph pattern specified by the path expressions in the MATCH clause
            foreach (var path in matchClause.Paths)
            {
                var index = 0;
                MatchEdge preEdge = null;
                for (var count = path.PathEdgeList.Count; index < count; ++index)
                {
                    var currentNodeTableRef = path.PathEdgeList[index].Item1;
                    var currentEdgeColumnRef = path.PathEdgeList[index].Item2;
                    var currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value;
                    var nextNodeTableRef = index != count - 1
                        ? path.PathEdgeList[index + 1].Item1
                        : path.Tail;
                    var nextNodeExposedName = nextNodeTableRef.BaseIdentifier.Value;
                    var patternNode = nodes.GetOrCreate(currentNodeExposedName);
                    if (patternNode.NodeAlias == null)
                    {
                        patternNode.NodeAlias = currentNodeExposedName;
                        patternNode.Neighbors = new List<MatchEdge>();
                        patternNode.External = false;
                        var nodeTable = _context[currentNodeExposedName] as WNamedTableReference;
                        if (nodeTable != null)
                        {
                            patternNode.NodeTableObjectName = nodeTable.TableObjectName;
                            if (patternNode.NodeTableObjectName.SchemaIdentifier == null)
                                patternNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                        }
                    }

                    Identifier edgeIdentifier = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last();
                    string schema = patternNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower();
                    string nodeTableName = patternNode.NodeTableObjectName.BaseIdentifier.Value;
                    string bindTableName =
                        _context.EdgeNodeBinding[
                            new Tuple<string, string>(nodeTableName.ToLower(), edgeIdentifier.Value.ToLower())].ToLower();
                    var bindNodeTableObjName = new WSchemaObjectName(
                        new Identifier {Value = schema},
                        new Identifier {Value = bindTableName}
                        );
                    var edgeColumn =
                        columnsOfNodeTables[
                            WNamedTableReference.SchemaNameToTuple(bindNodeTableObjName)][
                                currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value];
                    string edgeAlias = currentEdgeColumnRef.Alias;
                    //string revEdgeAlias = edgeAlias;
                    bool isReversed = path.IsReversed || edgeColumn.EdgeInfo.IsReversedEdge;
                    string currentRevEdgeName = null;

                    // get original edge name
                    var currentEdgeName = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().Value;
                    var originalSourceName = isReversed ?
                        (_context[nextNodeExposedName] as WNamedTableReference).TableObjectName.BaseIdentifier.Value
                        : (_context[currentNodeExposedName] as WNamedTableReference).TableObjectName.BaseIdentifier.Value;

                    if (isReversed)
                    {
                        var i = currentEdgeName.IndexOf(originalSourceName, StringComparison.OrdinalIgnoreCase) +
                            originalSourceName.Length;
                        currentRevEdgeName = currentEdgeName.Substring(i + 1,
                            currentEdgeName.Length - "Reversed".Length - i - 1);
                    }
                    else
                    {
                        var srcTuple = WNamedTableReference.SchemaNameToTuple(patternNode.NodeTableObjectName);
                        // [nodeView]-[edge]->[node/nodeView]
                        if (edgeColumn.Role == WNodeTableColumnRole.Edge && nodeViewMapping.ContainsKey(srcTuple))
                        {
                            var physicalNodeName =
                                _context.EdgeNodeBinding[new Tuple<string, string>(srcTuple.Item2, currentEdgeName.ToLower())];
                            currentRevEdgeName = physicalNodeName + "_" + currentEdgeName + "Reversed";
                        }
                        else
                        {
                            currentRevEdgeName = originalSourceName + "_" + currentEdgeName + "Reversed";
                        }
                    }

                    if (edgeAlias == null)
                    {
                        edgeAlias = !isReversed
                            ? string.Format("{0}_{1}_{2}", currentNodeExposedName, currentEdgeName, nextNodeExposedName)
                            : string.Format("{0}_{1}_{2}", nextNodeExposedName, currentRevEdgeName, currentNodeExposedName);

                        //when the current edge is a reversed edge, the key should still be the original edge name
                        //e.g.: TestDeleteEdgeWithTableAlias
                        var edgeNameKey = isReversed ? currentRevEdgeName : currentEdgeName;
                        if (edgeColumnToAliasesDict.ContainsKey(edgeNameKey))
                        {
                            edgeColumnToAliasesDict[edgeNameKey].Add(edgeAlias);
                        }
                        else
                        {
                            edgeColumnToAliasesDict.Add(edgeNameKey, new List<string> { edgeAlias });
                        }
                    }

                    MatchEdge edge, revEdge;
                    if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1)
                    {
                        var isEdgeView = edgeColumn.Role == WNodeTableColumnRole.EdgeView;
                        var hasRevEdge = edgeColumn.EdgeInfo.HasReversedEdge;
                        edge = new MatchEdge
                        {
                            IsEdgeView = isEdgeView,
                            IsReversedEdge = false,
                            HasReversedEdge = hasRevEdge,
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName = bindNodeTableObjName,
                        };
                        _context.AddEdgeReference(edge);

                        if (hasRevEdge)
                        {
                            revEdge = new MatchEdge
                            {
                                IsEdgeView = isEdgeView,
                                IsReversedEdge = true,
                                SinkNode = patternNode,
                                EdgeColumn = new WEdgeColumnReferenceExpression()
                                {
                                    ColumnType = currentEdgeColumnRef.ColumnType,
                                    Alias = currentEdgeColumnRef.Alias,
                                    MaxLength = currentEdgeColumnRef.MaxLength,
                                    MinLength = currentEdgeColumnRef.MinLength,
                                    AttributeValueDict = currentEdgeColumnRef.AttributeValueDict,
                                    MultiPartIdentifier = new WMultiPartIdentifier(new Identifier()
                                    {
                                        QuoteType = currentEdgeColumnRef.MultiPartIdentifier.Identifiers.Last().QuoteType,
                                        Value = currentRevEdgeName,
                                    }),
                                },
                                EdgeAlias = edgeAlias,
                                //EdgeAlias = revEdgeAlias,
                            };
                            reversedEdgeDict[edge.EdgeAlias] = revEdge;
                        }
                    }
                    else
                    {
                        MatchPath matchPath = new MatchPath
                        {
                            SourceNode = patternNode,
                            EdgeColumn = currentEdgeColumnRef,
                            EdgeAlias = edgeAlias,
                            BindNodeTableObjName =
                                new WSchemaObjectName(
                                    new Identifier {Value = schema},
                                    new Identifier {Value = bindTableName}
                                    ),
                            MinLength = currentEdgeColumnRef.MinLength,
                            MaxLength = currentEdgeColumnRef.MaxLength,
                            ReferencePathInfo = false,
                            AttributeValueDict = currentEdgeColumnRef.AttributeValueDict
                        };
                        _context.AddEdgeReference(matchPath);
                        pathDictionary[edgeAlias] = matchPath;
                        edge = matchPath;
                    }

                    if (preEdge != null)
                    {
                        preEdge.SinkNode = patternNode;
                        if (preEdge.HasReversedEdge)
                        {
                            //var preSourceNode = preEdge.SourceNode;
                            var preEdgeBindNodeTableObjName = preEdge.BindNodeTableObjName;
                            var preEdgeColName = preEdge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value;
                            var preEdgeColumn =
                                columnsOfNodeTables[
                                    WNamedTableReference.SchemaNameToTuple(preEdgeBindNodeTableObjName)][
                                        preEdgeColName];
                            var isEdgeView = preEdgeColumn.Role == WNodeTableColumnRole.EdgeView;
                            var isNodeView =
                                _graphMetaData.NodeViewMapping.ContainsKey(
                                    WNamedTableReference.SchemaNameToTuple(patternNode.NodeTableObjectName));

                            reversedEdgeDict[preEdge.EdgeAlias].SourceNode = patternNode;
                            // [node/nodeView]-[edgeView]->[node/nodeView]
                            if (isEdgeView)
                            {
                                reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = preEdgeBindNodeTableObjName;
                            }
                            // [node/nodeView]-[edge]->[nodeView]
                            else if (!isEdgeView && isNodeView)
                            {
                                reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                    new Identifier { Value = "dbo" },
                                    new Identifier { Value = preEdgeColumn.EdgeInfo.SinkNodes.First() }
                                    );
                            }
                            else
                            {
                                reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                    new Identifier { Value = schema },
                                    new Identifier { Value = bindTableName }
                                    );
                            }
                        }
                    }
                    preEdge = edge;

                    if (!parent.ContainsKey(currentNodeExposedName))
                        parent[currentNodeExposedName] = currentNodeExposedName;
                    if (!parent.ContainsKey(nextNodeExposedName))
                        parent[nextNodeExposedName] = nextNodeExposedName;

                    unionFind.Union(currentNodeExposedName, nextNodeExposedName);

                    patternNode.Neighbors.Add(edge);

                }
                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.NodeTableObjectName = nodeTable.TableObjectName;
                        if (tailNode.NodeTableObjectName.SchemaIdentifier == null)
                            tailNode.NodeTableObjectName.Identifiers.Insert(0, new Identifier {Value = "dbo"});
                    }
                }
                if (preEdge != null)
                {
                    preEdge.SinkNode = tailNode;
                    if (preEdge.HasReversedEdge)
                    {
                        var schema = tailNode.NodeTableObjectName.SchemaIdentifier.Value.ToLower();
                        var nodeTableName = tailNode.NodeTableObjectName.BaseIdentifier.Value;
                        //var preSourceNode = preEdge.SourceNode;
                        var preEdgeBindNodeTableObjName = preEdge.BindNodeTableObjName;
                        var preEdgeColName = preEdge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value;
                        var preEdgeColumn =
                            columnsOfNodeTables[
                                WNamedTableReference.SchemaNameToTuple(preEdgeBindNodeTableObjName)][
                                    preEdgeColName];
                        var isEdgeView = preEdgeColumn.Role == WNodeTableColumnRole.EdgeView;
                        var isNodeView =
                            _graphMetaData.NodeViewMapping.ContainsKey(
                                WNamedTableReference.SchemaNameToTuple(tailNode.NodeTableObjectName));
                        reversedEdgeDict[preEdge.EdgeAlias].SourceNode = tailNode;
                        // [node/nodeView]-[edgeView]->[node/nodeView]
                        if (isEdgeView)
                        {
                            reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = preEdgeBindNodeTableObjName;
                        }
                        // [node/nodeView]-[edge]->[nodeView]
                        else if (!isEdgeView && isNodeView)
                        {
                            reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                new Identifier { Value = "dbo" },
                                new Identifier { Value = preEdgeColumn.EdgeInfo.SinkNodes.First() }
                                );
                        }
                        else
                        {
                            reversedEdgeDict[preEdge.EdgeAlias].BindNodeTableObjName = new WSchemaObjectName(
                                new Identifier { Value = schema },
                                new Identifier { Value = nodeTableName.ToLower() }
                                );
                        }
                    }
                }
            }

            // Puts 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;
                }
            }

            var graph = new MatchGraph
            {
                ReversedEdgeDict = reversedEdgeDict,
                ConnectedSubGraphs = connectedSubGraphs,
                SourceNodeStatisticsDict = new Dictionary<Tuple<string, bool>, Statistics>(),
            };
            unionFind.Parent = null;

            // When an edge in the MATCH clause is not associated with an alias,
            // assigns to it a default alias: sourceAlias_EdgeColumnName_sinkAlias.
            // Also rewrites edge attributes anywhere in the query that can be bound to this default alias.
            var replaceTableRefVisitor = new ReplaceEdgeReferenceVisitor();
            replaceTableRefVisitor.Invoke(query, edgeColumnToAliasesDict);

            // Rematerializes node tables in the MATCH clause which are defined in the upper-level context
            // and join them with the upper-level table references.
            RematerilizeExtrenalNodeTableReference(query, nodes);

            // Transforms the path reference in the SELECT elements into a
            // scalar function to display path information.
            TransformPathInfoDisplaySelectElement(query, pathDictionary);

            return graph;
        }
        /// <summary>
        /// Estimates the average degree of the edges and retrieve density value.
        /// Send sa query to retrieve the varbinary of the sink in the edge sampling table with edge predicates,
        /// then generates the statistics histogram for each edge
        /// </summary>
        private void RetrieveStatistics(MatchGraph graph)
        {
            if (graph == null) throw new ArgumentNullException("graph");
            // Declare the parameters if any
            var declareParameter = "";
            if (_variables != null)
            {
                declareParameter = _variables.Aggregate(declareParameter,
                    (current, parameter) =>
                        current +
                        ("DECLARE " + parameter.VariableName.Value + " " +
                         TsqlFragmentToString.DataType(parameter.DataType) + "\r\n"));
            }

            // Calculates the average degree
            var sb = new StringBuilder();
            bool first = true;
            sb.Append("SELECT [Edge].*, [EdgeDegrees].[SampleRowCount], [EdgeDegrees].[AverageDegree] FROM");
            sb.Append("(\n");
            foreach (var edge in graph.ConnectedSubGraphs.SelectMany(subGraph => subGraph.Edges.Values))
            {
                if (!first)
                    sb.Append("\nUNION ALL\n");
                else
                {
                    first = false;
                }
                var tableObjectName = edge.SourceNode.NodeTableObjectName;
                string schema = tableObjectName.SchemaIdentifier.Value.ToLower();
                string tableName = tableObjectName.BaseIdentifier.Value.ToLower();
                string edgeName = edge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value.ToLower();
                string bindTableName = _context.EdgeNodeBinding[new Tuple<string, string>(tableName, edgeName)];

                // Distinguished between path and edge
                //var sinkColumnName = edge.IsPath ? "COUNT(Sink)" : "[dbo].[GraphViewUDFGlobalNodeIdEncoder](Sink)";
                sb.Append(
                    string.Format(@"
                            SELECT '{0}' as TableSchema,
                                   '{1}' as TableName,
                                   '{2}' as ColumnName,
                                   '{3}' as Alias,
                                   [dbo].[GraphViewUDFGlobalNodeIdEncoder](Src) as Src,
                                   [dbo].[GraphViewUDFGlobalNodeIdEncoder](Sink) as Sink,
                                   0 as IsReversed,
                                   NULL as OriginalEdgeAlias
                            FROM [{0}_{1}_{2}_Sampling] as [{3}]", schema,
                        bindTableName,
                        edgeName,
                        edge.EdgeAlias));
                var predicatesExpr = edge.RetrievePredicatesExpression();
                if (predicatesExpr!=null)
                    sb.AppendFormat("\n WHERE {0}", predicatesExpr);

                MatchEdge revEdge;
                if (graph.ReversedEdgeDict.TryGetValue(edge.EdgeAlias, out revEdge))
                {
                    sb.Append("\nUNION ALL\n");
                    var isEdgeView = revEdge.IsEdgeView;
                    var revTableObjectName = revEdge.SourceNode.NodeTableObjectName;
                    var revSchema = revTableObjectName.SchemaIdentifier.Value.ToLower();
                    var revEdgeName = revEdge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value.ToLower();
                    var revBindTableName = revEdge.BindNodeTableObjName.Identifiers.Last().Value.ToLower();
                    var revSamplingTableName = revSchema + "_" + revBindTableName + "_" + revEdgeName;
                    var revSrcTuple = WNamedTableReference.SchemaNameToTuple(revEdge.BindNodeTableObjName);
                    //var revSinkTuple = WNamedTableReference.SchemaNameToTuple(revEdge.SinkNode.NodeTableObjectName);
                    var originalEdgeName = edge.EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value.ToLower();
                    // [node/nodeView]-[edgeView]->[node/nodeView]
                    if (isEdgeView)
                    {
                        revEdgeName = revSrcTuple.Item2 + "_" + originalEdgeName + "Reversed";
                        revSamplingTableName = revSrcTuple.Item1 + "_" + revSrcTuple.Item2 + "_" + revEdgeName;
                    }

                    sb.Append(
                        string.Format(@"
                                SELECT '{0}' as TableSchema,
                                       '{1}' as TableName,
                                       '{2}' as ColumnName,
                                       '{3}' as Alias,
                                        [dbo].[GraphViewUDFGlobalNodeIdEncoder](Src) as Src,
                                        [dbo].[GraphViewUDFGlobalNodeIdEncoder](Sink) as Sink,
                                        1 as IsReversed,
                                       '{4}' as OriginalEdgeAlias
                                FROM [{5}_Sampling] as [{3}]", revSchema,
                            revBindTableName,
                            revEdgeName,
                            revEdge.EdgeAlias,
                            edge.EdgeAlias,
                            revSamplingTableName));
                    var revPredicatesExpr = revEdge.RetrievePredicatesExpression();
                    if (revPredicatesExpr != null)
                        sb.AppendFormat("\n WHERE {0}", revPredicatesExpr);
                }
            }
            sb.Append("\n) as Edge \n");
            sb.Append(String.Format(@"
                        INNER JOIN
                            [{0}] as [EdgeDegrees]
                        ON
                            [EdgeDegrees].[TableSchema] = [Edge].[TableSchema]
                        AND [EdgeDegrees].[TableName] = [Edge].[TableName]
                        AND [EdgeDegrees].[ColumnName] = [Edge].[ColumnName]", GraphViewConnection.MetadataTables[3]));

            using (var command = Tx.Connection.CreateCommand())
            {
                command.Transaction = Tx;
                command.CommandText = declareParameter + sb.ToString();
                using (var reader = command.ExecuteReader())
                {
                    var srcNodeStatisticsDict = graph.SourceNodeStatisticsDict;
                    while (reader.Read())
                    {
                        MatchEdge edge = null;
                        bool isReversed = reader["isReversed"].ToString().Equals("1");
                        if (!isReversed && !graph.TryGetEdge(reader["Alias"].ToString(), out edge))
                            throw new GraphViewException(string.Format("Edge {0} not exists", reader["Alias"].ToString()));
                        if (isReversed && !graph.TryGetEdge(reader["OriginalEdgeAlias"].ToString(), out edge))
                            throw new GraphViewException(string.Format("Edge {0} not exists", reader["OriginalEdgeAlias"].ToString()));
                        if (isReversed)
                            edge = graph.ReversedEdgeDict[edge.EdgeAlias];

                        var srcBytes = reader["Src"] as byte[];
                        var cursor = 0;
                        if (srcBytes != null)
                        {
                            var srcList = new List<long>();
                            while (cursor < srcBytes.Length)
                            {
                                var src = BitConverter.ToInt64(srcBytes, cursor);
                                cursor += 8;
                                srcList.Add(src);
                            }
                            var tmpEdge = new MatchEdge();
                            Statistics.UpdateEdgeHistogram(tmpEdge, srcList);
                            srcNodeStatisticsDict[new Tuple<string, bool>(edge.EdgeAlias, isReversed)] = tmpEdge.Statistics;
                        }
                        else
                            srcNodeStatisticsDict[new Tuple<string, bool>(edge.EdgeAlias, isReversed)] = null;

                        var sinkBytes = reader["Sink"] as byte[];
                        if (sinkBytes == null)
                        {
                            edge.Statistics = new Statistics
                            {
                                Density = 0,
                                Histogram = new Dictionary<long, Tuple<double, bool>>(),
                                MaxValue = 0,
                                RowCount = 0,
                                //Selectivity = 1.0
                            };
                            continue;
                        }
                        List<long> sinkList = new List<long>();
                        cursor = 0;
                        while (cursor < sinkBytes.Length)
                        {
                            var sink = BitConverter.ToInt64(sinkBytes, cursor);
                            cursor += 8;
                            sinkList.Add(sink);
                        }
                        Statistics.UpdateEdgeHistogram(edge, sinkList);
                        edge.AverageDegree = Convert.ToDouble(reader["AverageDegree"])*sinkList.Count*1.0/
                                             Convert.ToInt64(reader["SampleRowCount"]);
                        var path = edge as MatchPath;
                        if (path != null)
                        {
                            if (path.AverageDegree > 1)
                                if (path.MaxLength != -1)
                                {
                                    path.AverageDegree = Math.Pow(path.AverageDegree, path.MaxLength) -
                                                         (path.MinLength > 0
                                                             ? Math.Pow(path.AverageDegree, path.MinLength - 1)
                                                             : 0);
                                }
                                else
                                    path.AverageDegree = double.MaxValue;
                        }

                    }
                }

                // Retrieves density value for each node table
                string tempTableName = Path.GetRandomFileName().Replace(".", "").Substring(0, 8);
                var dbccDensityQuery = new StringBuilder();
                dbccDensityQuery.Append(string.Format(@"CREATE TABLE #{0} (Density float, Len int, Col sql_variant);
                                                    INSERT INTO #{0} EXEC('", tempTableName));
                Dictionary<Tuple<string, string>, List<MatchNode>> schemaTableToNodeListMapping =
                    new Dictionary<Tuple<string, string>, List<MatchNode>>();
                foreach (var subGraph in graph.ConnectedSubGraphs)
                {
                    foreach (var node in subGraph.Nodes.Values)
                    {
                        var tableTuple = WNamedTableReference.SchemaNameToTuple(node.NodeTableObjectName);
                        if (_graphMetaData.NodeViewMapping.ContainsKey(tableTuple))
                        {
                            node.GlobalNodeIdDensity = Statistics.DefaultDensity;
                        }
                        else
                        {
                            var nodeList = schemaTableToNodeListMapping.GetOrCreate(tableTuple);
                            nodeList.Add(node);
                        }

                    }
                }
                foreach (var tableTuple in schemaTableToNodeListMapping.Keys)
                {
                    dbccDensityQuery.Append(string.Format(
                        "DBCC SHOW_STATISTICS (\"{0}.{1}\", [{0}{1}_PK_GlobalNodeId]) with DENSITY_VECTOR;\n",
                        tableTuple.Item1,
                        tableTuple.Item2));
                }
                dbccDensityQuery.Append("');\n");
                dbccDensityQuery.Append(string.Format("SELECT Density FROM #{0} WHERE Col = 'GlobalNodeId'", tempTableName));
                command.CommandText = dbccDensityQuery.ToString();
                using (var reader = command.ExecuteReader())
                {
                    foreach (var item in schemaTableToNodeListMapping)
                    {
                        double density;
                        if (!reader.Read())
                            density = Statistics.DefaultDensity;
                        else
                        {
                            density = Convert.ToDouble(reader["Density"]);
                            if (Math.Abs(density - 1.0) < 0.0001)
                                density = Statistics.DefaultDensity;
                        }

                        foreach (var node in item.Value)
                        {
                            node.GlobalNodeIdDensity = density;
                        }
                    }
                }
            }
        }
示例#13
0
        /// <summary>
        /// Item1: current node. A query will be sent to the server to fetch this node if this is the first time it appears in the whole list.
        /// Item2: the traversalEdge whose sink is current node.
        /// Item3: traversalEdges whose source is currentNode.
        ///        This list will either contain 0 or 1 traversal edge in the current version, and it will be pushed to server if possible.
        /// Item4: backwardMatchingEdges.
        /// Item5: forwardMatchingEdges.
        /// </summary>
        /// <param name="traversalChain"></param>
        /// <returns></returns>
        protected List <Tuple <MatchNode, MatchEdge, List <MatchEdge>, List <MatchEdge>, List <MatchEdge> > > GenerateTraversalOrderFromTraversalChain
            (List <Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> > > traversalChain)
        {
            Dictionary <string, int> nodeFetchingOrderDict = new Dictionary <string, int>();
            List <Tuple <MatchNode, MatchEdge, List <MatchEdge>, List <MatchEdge>, List <MatchEdge> > > optimizedTraversalOrder
                = new List <Tuple <MatchNode, MatchEdge, List <MatchEdge>, List <MatchEdge>, List <MatchEdge> > >();

            foreach (Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> > tuple in traversalChain)
            {
                MatchNode srcNode       = tuple.Item1;
                MatchEdge traversalEdge = tuple.Item2;

                int nodeFetchingOrder;
                if (nodeFetchingOrderDict.TryGetValue(srcNode.NodeAlias, out nodeFetchingOrder))
                {
                    List <MatchEdge> traversalEdges = optimizedTraversalOrder[nodeFetchingOrder].Item3;
                    if (traversalEdges.Count == 0)
                    {
                        traversalEdges.Add(traversalEdge);
                    }
                    else
                    {
                        optimizedTraversalOrder.Add(
                            new Tuple <MatchNode, MatchEdge, List <MatchEdge>, List <MatchEdge>, List <MatchEdge> >(
                                srcNode,
                                null,
                                new List <MatchEdge> {
                            traversalEdge
                        },
                                new List <MatchEdge>(), new List <MatchEdge>()));
                    }
                }
                else
                {
                    nodeFetchingOrderDict.Add(srcNode.NodeAlias, optimizedTraversalOrder.Count);
                    optimizedTraversalOrder.Add(
                        new Tuple <MatchNode, MatchEdge, List <MatchEdge>, List <MatchEdge>, List <MatchEdge> >(
                            srcNode,
                            null,
                            traversalEdge != null ? new List <MatchEdge> {
                        traversalEdge
                    } : new List <MatchEdge>(),
                            new List <MatchEdge>(), new List <MatchEdge>()));
                }

                if (traversalEdge != null)
                {
                    MatchNode        sinkNode      = tuple.Item3;
                    List <MatchEdge> backwardEdges = tuple.Item4;
                    List <MatchEdge> forwardEdges  = tuple.Item5;

                    nodeFetchingOrderDict.Add(sinkNode.NodeAlias, optimizedTraversalOrder.Count);
                    optimizedTraversalOrder.Add(
                        new Tuple <MatchNode, MatchEdge, List <MatchEdge>, List <MatchEdge>, List <MatchEdge> >(
                            sinkNode,
                            traversalEdge,
                            new List <MatchEdge>(),
                            backwardEdges, forwardEdges));
                }
            }

            return(optimizedTraversalOrder);
        }
示例#14
0
 /// <summary>
 /// Span the table given the edge using cross apply
 /// </summary>
 /// <param name="tableRef"></param>
 /// <param name="edge"></param>
 /// <param name="nodeAlias"></param>
 /// <param name="dumbNode"></param>
 /// <returns></returns>
 public WTableReference SpanTableRef(WTableReference tableRef, MatchEdge edge, string nodeAlias, string dumbNode, GraphMetaData metaData)
 {
     tableRef = new WUnqualifiedJoin
     {
         FirstTableRef = tableRef,
         SecondTableRef = edge.ToSchemaObjectFunction(nodeAlias, dumbNode, metaData),
         UnqualifiedJoinType = UnqualifiedJoinType.CrossApply,
     };
     return tableRef;
 }
示例#15
0
 public ColumnStatistics GetEdgeStatistics(MatchEdge edge)
 {
     return(_edgeStatisticses[edge]);
 }
示例#16
0
 public ColumnStatistics GetEdgeStatistics(MatchEdge edge)
 {
     return _edgeStatisticses[edge];
 }
示例#17
0
 internal bool TryGetEdge(string alias, out MatchEdge edge)
 {
     return(this.GraphPattern.TryGetEdge(alias, out edge));
 }
示例#18
0
 public void AddEdgeReference(MatchEdge edge)
 {
     var edgeAlias = edge.EdgeAlias;
     if (_nodeTableDictionary.ContainsKey(edgeAlias) || _edgeDictionary.ContainsKey(edgeAlias))
         throw new GraphViewException("Duplicate Alias");
     _edgeDictionary.Add(edgeAlias,
         new Tuple<WSchemaObjectName, WColumnReferenceExpression>(edge.SourceNode.NodeTableObjectName,
             edge.EdgeColumn));
 }
        /// <summary>
        /// Update the statistics histogram for the edge given the sink id list.
        /// Bucket size is pre-defined
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="sinkList"></param>
        private void UpdateEdgeHistogram(MatchEdge edge, List<long> sinkList)
        {
            sinkList.Sort();
            var rowCount = sinkList.Count;
            var statistics = new ColumnStatistics
            {
                RowCount = rowCount
            };
            var height = (int)(rowCount / BucketNum);
            var popBucketCount = 0;
            var popValueCount = 0;
            var bucketCount = 0;
            // If number in each bucket is very small, then generate a Frequency Histogram
            if (height < 2)
            {
                bucketCount = rowCount;
                long preValue = sinkList[0];
                int count = 1;
                int distCount = 1;
                for (int i = 1; i < rowCount; i++)
                {
                    var curValue = sinkList[i];
                    if (curValue == preValue)
                    {
                        count++;
                    }
                    else
                    {
                        if (count > 1)
                        {
                            popBucketCount += count;
                            popValueCount++;
                        }
                        statistics.Histogram.Add(preValue, new Tuple<double, bool>(count, count > 1));
                        count = 1;
                        preValue = curValue;
                        distCount++;
                    }
                }
                if (count > 1)
                {
                    popBucketCount += count;
                    popValueCount++;
                }
                statistics.Histogram.Add(preValue, new Tuple<double, bool>(count, count > 1));
                statistics.MaxValue = preValue;
                // Simple Denstity
                //statistics.Density = 1.0 / distCount;
                // Advanced Density
                statistics.Density = bucketCount == popBucketCount
                    ? 0
                    : 1.0 * (bucketCount - popBucketCount) / bucketCount / (distCount - popValueCount);
            }

            // Generate a Height-balanced Histogram
            else
            {
                long preValue = sinkList[0];
                int count = 0;
                int distCount = 1;
                for (int i = 1; i < rowCount; i++)
                {
                    if (i % height == height - 1)
                    {
                        bucketCount++;
                        var curValue = sinkList[i];
                        if (curValue == preValue)
                            count += height;
                        else
                        {
                            distCount++;
                            if (count > height)
                            {
                                popBucketCount += count / height;
                                popValueCount++;
                            }
                            //count = count == 0 ? height : count;
                            statistics.Histogram.Add(preValue, new Tuple<double, bool>(count, count > height));
                            preValue = curValue;
                            count = height;
                        }
                    }
                }
                if (count > height)
                {
                    popBucketCount += count / height;
                    popValueCount++;
                }
                statistics.Histogram.Add(preValue, new Tuple<double, bool>(count, count > height));
                statistics.MaxValue = preValue;
                // Simple Density
                //statistics.Density = 1.0 / distCount;
                // Advanced Density
                statistics.Density = bucketCount == popBucketCount
                    ? 0
                    : 1.0 * (bucketCount - popBucketCount) / bucketCount / (distCount - popValueCount);
            }
            _context.AddEdgeStatistics(edge, statistics);
        }
        /// <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;
        }
示例#21
0
        private void UpdateComponent(MatchComponent curComponent, CandidateJoinUnit candidateTree)
        {
            Dictionary <string, MatchNode>            nodes = curComponent.Nodes;
            Dictionary <MatchEdge, bool>              edgeMaterializedDict      = curComponent.EdgeMaterilizedDict;
            Dictionary <MatchNode, List <MatchEdge> > unmaterializedNodeMapping = curComponent.UnmaterializedNodeMapping;
            MatchNode root = candidateTree.TreeRoot;

            if (!nodes.ContainsKey(root.NodeAlias))
            {
                nodes.Add(root.NodeAlias, new MatchNode(root));
            }
            curComponent.MaterializedNodeSplitCount[root] = 0;

            List <Tuple <MaterializedOrder, MatchEdge> > 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();

            List <Tuple <MaterializedOrder, MatchEdge> > 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();

            if (inEdges.Any())
            {
                unmaterializedNodeMapping.Remove(root);

                foreach (Tuple <MaterializedOrder, MatchEdge> t in inEdges)
                {
                    MaterializedOrder order = t.Item1;
                    MatchEdge         edge  = t.Item2;

                    edgeMaterializedDict[edge] = true;
                    List <string> adjListProperties = this.PopulateAdjacencyListProperties(edge);
                    MatchNode     node = curComponent.Nodes[edge.SourceNode.NodeAlias];
                    foreach (string adjListProperty in adjListProperties)
                    {
                        node.Properties.Add(adjListProperty);
                    }
                }
            }

            if (outEdges.Any())
            {
                foreach (Tuple <MaterializedOrder, MatchEdge> t in outEdges)
                {
                    MaterializedOrder order = t.Item1;
                    MatchEdge         edge  = t.Item2;

                    edgeMaterializedDict[edge] = true;
                    List <string> adjListProperties = this.PopulateAdjacencyListProperties(edge);
                    MatchNode     node = curComponent.Nodes[edge.SourceNode.NodeAlias];
                    foreach (string adjListProperty in adjListProperties)
                    {
                        node.Properties.Add(adjListProperty);
                    }
                }
            }

            List <MatchEdge> unmatEdges = candidateTree.UnmaterializedEdges;

            foreach (MatchEdge unmatEdge in unmatEdges)
            {
                edgeMaterializedDict[unmatEdge] = false;;
                List <MatchEdge> unmatNodeInEdges = unmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode);
                unmatNodeInEdges.Add(unmatEdge);
            }
        }
示例#22
0
        /// <summary>
        /// Updates the statistics histogram for the edge given the sink id list.
        /// Bucket size is pre-defined
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="sinkList">sink id of the edge sampling</param>
        internal static void UpdateEdgeHistogram(MatchEdge edge, List <long> sinkList)
        {
            sinkList.Sort();
            var rowCount   = sinkList.Count;
            var statistics = new Statistics
            {
                RowCount = rowCount,
            };
            var height         = (int)(rowCount / BucketNum);
            var popBucketCount = 0;
            var popValueCount  = 0;
            var bucketCount    = 0;

            // If number in each bucket is very small, then generate a Frequency Histogram
            if (height < 2)
            {
                bucketCount = rowCount;
                long preValue  = sinkList[0];
                int  count     = 1;
                int  distCount = 1;
                for (int i = 1; i < rowCount; i++)
                {
                    var curValue = sinkList[i];
                    if (curValue == preValue)
                    {
                        count++;
                    }
                    else
                    {
                        if (count > 1)
                        {
                            popBucketCount += count;
                            popValueCount++;
                        }
                        statistics.Histogram.Add(preValue, new Tuple <double, bool>(count, count > 1));
                        count    = 1;
                        preValue = curValue;
                        distCount++;
                    }
                }
                if (count > 1)
                {
                    popBucketCount += count;
                    popValueCount++;
                }
                statistics.Histogram.Add(preValue, new Tuple <double, bool>(count, count > 1));
                statistics.MaxValue = preValue;
                // Simple Denstity
                //statistics.Density = 1.0 / distCount;
                // Advanced Density
                statistics.Density = bucketCount == popBucketCount
                    ? 0
                    : 1.0 * (bucketCount - popBucketCount) / bucketCount / (distCount - popValueCount);
            }

            // Generates a Height-balanced Histogram
            else
            {
                long preValue  = sinkList[0];
                int  count     = 0;
                int  distCount = 1;
                for (int i = 1; i < rowCount; i++)
                {
                    if (i % height == height - 1)
                    {
                        bucketCount++;
                        var curValue = sinkList[i];
                        if (curValue == preValue)
                        {
                            count += height;
                        }
                        else
                        {
                            distCount++;
                            if (count > height)
                            {
                                popBucketCount += count / height;
                                popValueCount++;
                            }
                            //count = count == 0 ? height : count;
                            statistics.Histogram.Add(preValue, new Tuple <double, bool>(count, count > height));
                            preValue = curValue;
                            count    = height;
                        }
                    }
                }
                if (count > height)
                {
                    popBucketCount += count / height;
                    popValueCount++;
                }
                statistics.Histogram.Add(preValue, new Tuple <double, bool>(count, count > height));
                statistics.MaxValue = preValue;
                // Simple Density
                //statistics.Density = 1.0 / distCount;
                // Advanced Density
                statistics.Density = bucketCount == popBucketCount
                    ? 0
                    : 1.0 * (bucketCount - popBucketCount) / bucketCount / (distCount - popValueCount);
            }
            edge.Statistics = statistics;
        }
示例#23
0
        /// <summary>
        /// Generate the Table-Valued Function by the edge given the node alias
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="nodeAlias"></param>
        /// <returns></returns>
        private static WTableReference EdgeToTableReference(MatchEdge edge, string nodeAlias)
        {
            var edgeColumn = edge.EdgeColumn;
            var edgeIdentifiers = edge.EdgeColumn.MultiPartIdentifier.Identifiers;
            if (nodeAlias != edgeIdentifiers.First().Value)
            {
                var identifiers = new List<Identifier>(edgeIdentifiers);
                identifiers.RemoveAt(0);
                identifiers.Insert(0, new Identifier
                {
                    Value = nodeAlias
                });
                edgeColumn = new WColumnReferenceExpression
                {
                    MultiPartIdentifier = new WMultiPartIdentifier
                    {
                        Identifiers = identifiers
                    }
                };
                
            }
            var columnName = edgeIdentifiers.Last().Value;
            var deColIdentifiers = new Identifier[]
            {
                edgeColumn.MultiPartIdentifier.Identifiers.First(),
                new Identifier {Value = columnName + "DeleteCol"}
            };
            var decoderFunction = new Identifier
            {
                Value = edge.SourceNode.TableObjectName.SchemaIdentifier.Value + '_' +
                        edge.SourceNode.TableObjectName.BaseIdentifier.Value + '_' + 
                        columnName + '_' +
                        "Decoder",

            };
            var tableRef = new WSchemaObjectFunctionTableReference
            {
                SchemaObject = new WSchemaObjectName(
                    new Identifier {Value = "dbo"},
                    decoderFunction),
                Parameters = new List<WScalarExpression>
                {
                    edgeColumn,
                    new WColumnReferenceExpression
                    {
                        MultiPartIdentifier = new WMultiPartIdentifier(deColIdentifiers)
                    }
                },
                Alias = new Identifier
                {
                    Value = edge.EdgeAlias,
                }
            };
            return tableRef;
        }
示例#24
0
 public void AddEdgeStatistics(MatchEdge edge, ColumnStatistics statistics)
 {
     _edgeStatisticses.Add(edge, statistics);
 }
示例#25
0
 /// <summary>
 /// Span the table given the edge using cross apply
 /// </summary>
 /// <param name="tableRef"></param>
 /// <param name="edge"></param>
 /// <param name="nodeAlias"></param>
 /// <returns></returns>
 public static WTableReference SpanTableRef(WTableReference tableRef, MatchEdge edge, string nodeAlias)
 {
     tableRef = new WUnqualifiedJoin
     {
         FirstTableRef = tableRef,
         SecondTableRef = EdgeToTableReference(edge, nodeAlias),
         UnqualifiedJoinType = UnqualifiedJoinType.CrossApply,
     };
     return tableRef;
 }
示例#26
0
 public bool TryGetEdge(string key, out MatchEdge edge)
 {
     foreach (var subGraph in ConnectedSubGraphs)
     {
         if (subGraph.Edges.TryGetValue(key, out edge))
         {
             return true;
         }
     }
     edge = null;
     return false;
 }
示例#27
0
        // Greate the MatchGraph of this AggregationBlock. If some free nodes and free edges are connected, they are in the same ConnectedComponent
        internal HashSet <string> CreateMatchGraph(WMatchClause matchClause)
        {
            HashSet <string> freeNodesAndEdges = new HashSet <string>();
            Dictionary <string, MatchPath>          pathCollection     = new Dictionary <string, MatchPath>(StringComparer.OrdinalIgnoreCase);
            Dictionary <string, MatchNode>          nodeCollection     = new Dictionary <string, MatchNode>(StringComparer.OrdinalIgnoreCase);
            Dictionary <string, MatchEdge>          edgeCollection     = new Dictionary <string, MatchEdge>(StringComparer.OrdinalIgnoreCase);
            Dictionary <string, ConnectedComponent> subgraphCollection = new Dictionary <string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase);

            // we use Disjoint-set data structure to determine whether tables are in the same component or not.
            UnionFind unionFind = new UnionFind();

            foreach (ConnectedComponent subgraph in this.GraphPattern.ConnectedSubgraphs)
            {
                foreach (KeyValuePair <string, MatchNode> pair in subgraph.Nodes)
                {
                    nodeCollection.Add(pair.Key, pair.Value);
                    unionFind.Add(pair.Key);
                }
            }

            if (matchClause != null)
            {
                foreach (WMatchPath path in matchClause.Paths)
                {
                    int       index         = 0;
                    bool      outOfBlock    = false;
                    MatchEdge edgeToSrcNode = null;

                    for (int count = path.PathEdgeList.Count; index < count; ++index)
                    {
                        WSchemaObjectName currentNodeTableRef = path.PathEdgeList[index].Item1;
                        WEdgeColumnReferenceExpression currentEdgeColumnRef = path.PathEdgeList[index].Item2;
                        WSchemaObjectName nextNodeTableRef = index != count - 1
                            ? path.PathEdgeList[index + 1].Item1
                            : path.Tail;
                        string currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value;
                        string edgeAlias           = currentEdgeColumnRef.Alias;
                        string nextNodeExposedName = nextNodeTableRef != null ? nextNodeTableRef.BaseIdentifier.Value : null;

                        // Get the source node of a path
                        if (!nodeCollection.ContainsKey(currentNodeExposedName))
                        {
                            continue;
                        }
                        MatchNode srcNode = nodeCollection[currentNodeExposedName];

                        // Get the edge of a path, and set required attributes
                        // Because the sourceNode is relative, we need to construct new edges or paths
                        // But they need to share the same predicates and proerties
                        MatchEdge edgeFromSrcNode;
                        if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1)
                        {
                            if (!edgeCollection.ContainsKey(edgeAlias))
                            {
                                edgeCollection[edgeAlias] = new MatchEdge()
                                {
                                    LinkAlias            = edgeAlias,
                                    SourceNode           = srcNode,
                                    EdgeType             = currentEdgeColumnRef.EdgeType,
                                    Predicates           = new List <WBooleanExpression>(),
                                    BindNodeTableObjName = new WSchemaObjectName(),
                                    IsReversed           = false,
                                    Properties           = new List <string>(GraphViewReservedProperties.ReservedEdgeProperties)
                                };
                                unionFind.Add(edgeAlias);
                            }

                            edgeFromSrcNode = new MatchEdge
                            {
                                LinkAlias            = edgeAlias,
                                SourceNode           = srcNode,
                                EdgeType             = edgeCollection[edgeAlias].EdgeType,
                                Predicates           = edgeCollection[edgeAlias].Predicates,
                                BindNodeTableObjName = edgeCollection[edgeAlias].BindNodeTableObjName,
                                IsReversed           = false,
                                Properties           = edgeCollection[edgeAlias].Properties
                            };
                        }
                        else
                        {
                            if (!pathCollection.ContainsKey(edgeAlias))
                            {
                                pathCollection[edgeAlias] = new MatchPath
                                {
                                    SourceNode           = srcNode,
                                    LinkAlias            = edgeAlias,
                                    Predicates           = new List <WBooleanExpression>(),
                                    BindNodeTableObjName = new WSchemaObjectName(),
                                    MinLength            = currentEdgeColumnRef.MinLength,
                                    MaxLength            = currentEdgeColumnRef.MaxLength,
                                    ReferencePathInfo    = false,
                                    AttributeValueDict   = currentEdgeColumnRef.AttributeValueDict,
                                    IsReversed           = false,
                                    EdgeType             = currentEdgeColumnRef.EdgeType,
                                    Properties           = new List <string>(GraphViewReservedProperties.ReservedEdgeProperties)
                                };
                            }

                            edgeFromSrcNode = new MatchPath
                            {
                                SourceNode           = srcNode,
                                LinkAlias            = edgeAlias,
                                Predicates           = pathCollection[edgeAlias].Predicates,
                                BindNodeTableObjName = pathCollection[edgeAlias].BindNodeTableObjName,
                                MinLength            = pathCollection[edgeAlias].MinLength,
                                MaxLength            = pathCollection[edgeAlias].MaxLength,
                                ReferencePathInfo    = false,
                                AttributeValueDict   = pathCollection[edgeAlias].AttributeValueDict,
                                IsReversed           = false,
                                EdgeType             = pathCollection[edgeAlias].EdgeType,
                                Properties           = pathCollection[edgeAlias].Properties
                            };
                        }

                        if (path.IsReversed)
                        {
                            unionFind.Union(edgeAlias, currentNodeExposedName);
                        }
                        else
                        {
                            unionFind.Union(currentNodeExposedName, edgeAlias);
                        }

                        if (edgeToSrcNode != null)
                        {
                            edgeToSrcNode.SinkNode = srcNode;

                            if (!(edgeToSrcNode is MatchPath))
                            {
                                // Construct reverse edge
                                MatchEdge reverseEdge = new MatchEdge
                                {
                                    SourceNode           = edgeToSrcNode.SinkNode,
                                    SinkNode             = edgeToSrcNode.SourceNode,
                                    LinkAlias            = edgeToSrcNode.LinkAlias,
                                    Predicates           = edgeToSrcNode.Predicates,
                                    BindNodeTableObjName = edgeToSrcNode.BindNodeTableObjName,
                                    IsReversed           = true,
                                    EdgeType             = edgeToSrcNode.EdgeType,
                                    Properties           = edgeToSrcNode.Properties,
                                };
                                srcNode.ReverseNeighbors.Add(reverseEdge);
                            }
                        }

                        edgeToSrcNode = edgeFromSrcNode;

                        // Add this edge to node's neightbors
                        if (nextNodeExposedName != null)
                        {
                            if (path.IsReversed)
                            {
                                unionFind.Union(nextNodeExposedName, edgeAlias);
                            }
                            else
                            {
                                unionFind.Union(edgeAlias, nextNodeExposedName);
                            }

                            srcNode.Neighbors.Add(edgeFromSrcNode);
                        }
                        // Add this edge to node's dangling edges
                        else
                        {
                            srcNode.DanglingEdges.Add(edgeFromSrcNode);
                        }
                    }

                    if (path.Tail == null)
                    {
                        continue;
                    }

                    // Get destination node of a path
                    string tailExposedName = path.Tail.BaseIdentifier.Value;

                    if (!nodeCollection.ContainsKey(tailExposedName))
                    {
                        continue;
                    }

                    MatchNode destNode = nodeCollection[tailExposedName];

                    if (edgeToSrcNode != null)
                    {
                        edgeToSrcNode.SinkNode = destNode;
                        if (!(edgeToSrcNode is MatchPath))
                        {
                            // Construct reverse edge
                            MatchEdge reverseEdge = new MatchEdge
                            {
                                SourceNode           = edgeToSrcNode.SinkNode,
                                SinkNode             = edgeToSrcNode.SourceNode,
                                LinkAlias            = edgeToSrcNode.LinkAlias,
                                Predicates           = edgeToSrcNode.Predicates,
                                BindNodeTableObjName = edgeToSrcNode.BindNodeTableObjName,
                                IsReversed           = true,
                                EdgeType             = edgeToSrcNode.EdgeType,
                                Properties           = edgeToSrcNode.Properties,
                            };
                            destNode.ReverseNeighbors.Add(reverseEdge);
                        }
                    }
                }
            }

            // Use union find algorithmn to define which subgraph does a node belong to and put it into where it belongs to.
            foreach (var node in nodeCollection)
            {
                freeNodesAndEdges.Add(node.Key);
                string root = unionFind.Find(node.Key);

                ConnectedComponent subGraph;
                if (!subgraphCollection.ContainsKey(root))
                {
                    subGraph = new ConnectedComponent();
                    subgraphCollection[root] = subGraph;
                }
                else
                {
                    subGraph = subgraphCollection[root];
                }

                subGraph.Nodes[node.Key] = node.Value;

                subGraph.IsTailNode[node.Value] = false;

                foreach (MatchEdge edge in node.Value.Neighbors)
                {
                    subGraph.Edges[edge.LinkAlias] = edge;
                    freeNodesAndEdges.Add(edge.LinkAlias);
                }

                foreach (MatchEdge edge in node.Value.DanglingEdges)
                {
                    subGraph.Edges[edge.LinkAlias] = edge;
                    edge.IsDanglingEdge            = true;
                    freeNodesAndEdges.Add(edge.LinkAlias);
                }

                if (node.Value.Neighbors.Count + node.Value.ReverseNeighbors.Count + node.Value.DanglingEdges.Count > 0)
                {
                    node.Value.Properties.Add(GremlinKeyword.Star);
                }
            }

            this.GraphPattern = new MatchGraph(subgraphCollection.Values.ToList());

            return(freeNodesAndEdges);
        }
示例#28
0
 public void AddEdgeStatistics(MatchEdge edge, ColumnStatistics statistics)
 {
     _edgeStatisticses.Add(edge, statistics);
 }