Inheritance: WMultiPartIdentifier
        public static string WSchemaObjectName(WSchemaObjectName sobj)
        {
            var sb    = new StringBuilder(128);
            var empty = true;

            if (sobj.ServerIdentifier != null)
            {
                sb.Append(sobj.ServerIdentifier.Value);
                empty = false;
            }

            if (sobj.DatabaseIdentifier != null)
            {
                if (!empty)
                {
                    sb.Append('.');
                }

                sb.Append(sobj.DatabaseIdentifier.Value);
                empty = false;
            }

            if (sobj.BaseIdentifier == null)
            {
                return(sb.ToString());
            }
            if (!empty)
            {
                sb.Append('.');
            }

            sb.Append(sobj.BaseIdentifier.Value);

            return(sb.ToString());
        }
Esempio n. 2
0
        public override void Visit(WMatchPath node)
        {
            foreach (var sourceEdge in node.PathEdgeList)
            {
                WSchemaObjectName source            = sourceEdge.Item1;
                string            tableAlias        = source.BaseIdentifier.Value;
                WEdgeColumnReferenceExpression edge = sourceEdge.Item2;

                if (accessedColumns.ContainsKey(tableAlias))
                {
                    switch (edge.EdgeType)
                    {
                    case WEdgeType.OutEdge:
                        accessedColumns[tableAlias].Add(ColumnGraphType.OutAdjacencyList.ToString());
                        break;

                    case WEdgeType.InEdge:
                        accessedColumns[tableAlias].Add(ColumnGraphType.InAdjacencyList.ToString());
                        break;

                    case WEdgeType.BothEdge:
                        accessedColumns[tableAlias].Add(ColumnGraphType.BothAdjacencyList.ToString());
                        break;

                    default:
                        break;
                    }
                }
            }
        }
 public void AddEdgeReference(string name, WSchemaObjectName sourceNodeName, WEdgeColumnReferenceExpression edgeReference)
 {
     if (_nodeTableDictionary.ContainsKey(name) || _edgeDictionary.ContainsKey(name))
     {
         throw new GraphViewException("Duplicate Alias");
     }
     _edgeDictionary.Add(name,
                         new Tuple <WSchemaObjectName, WEdgeColumnReferenceExpression>(sourceNodeName, edgeReference));
 }
Esempio n. 4
0
 internal static Tuple <string, string> SchemaNameToTuple(WSchemaObjectName name)
 {
     return
         (name == null
             ? null
             : new Tuple <string, string>(
              name.SchemaIdentifier == null
                     ? "dbo"
                     : name.SchemaIdentifier.Value.ToLower(CultureInfo.CurrentCulture),
              name.BaseIdentifier.Value.ToLower(CultureInfo.CurrentCulture)));
 }
Esempio n. 5
0
 private WSchemaObjectName ParseSchemaObjectName(SchemaObjectName name)
 {
     if (name == null)
         return null;
     var wSchemaObjectName = new WSchemaObjectName
     {
         FirstTokenIndex = name.FirstTokenIndex,
         LastTokenIndex = name.LastTokenIndex,
     };
     if (name.Identifiers != null)
     {
         wSchemaObjectName.Identifiers = new List<Identifier>();
         foreach (var identifier in name.Identifiers)
         {
             if (GraphViewKeywords._keywords.Contains(identifier.Value))
             {
                 var token = _tokens[identifier.FirstTokenIndex];
                 throw new SyntaxErrorException(token.Line, identifier.Value,
                     "System restricted Name cannot be used");
             }
             wSchemaObjectName.Identifiers.Add(identifier);
         }
     }
     return wSchemaObjectName;
 }
Esempio n. 6
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);
        }
Esempio n. 7
0
        private static bool ParseNodeTableColumn(
            IList<TSqlParserToken> tokens,
            ref int nextToken,
            ref WNodeTableColumn result,
            ref int farestError)
        {
            var currentToken = nextToken;
            var firstToken = nextToken;
            var lastToken = nextToken;
            var metaDataStr = "";
            // Quoted identifier is an expression inside a pair of brackets [ ... ]
            if (!ReadToken(tokens, TSqlTokenType.QuotedIdentifier, ref metaDataStr, ref currentToken, ref farestError))
                return false;

            Identifier columnName = null;
            if (!ParseIdentifier(tokens, ref currentToken, ref columnName, ref farestError))
                return false;

            WDataTypeReference dataType = null;
            if (!ParseDataType(tokens, ref currentToken, ref dataType, ref farestError))
                return false;

            HashSet<string> metaDataFields = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase)
            {
                "columnrole",
                "reference",
                "attributes"
            }; 

            metaDataStr = '{' + metaDataStr.Substring(1, metaDataStr.Length - 2) + '}';

            var metaStrToken = tokens[firstToken];
            var tokenErrorKey = "";
            List<AnnotationToken> annotationTokens = LexicalAnalyzer.Tokenize(metaDataStr, ref tokenErrorKey);
            if (annotationTokens == null)
            {
                throw new SyntaxErrorException(metaStrToken.Line, tokenErrorKey);
            }
            int startToken = 0, fareastError = -1;
            NestedObject nestedObj = null;
            ParseNestedObject(annotationTokens, ref startToken, ref nestedObj, ref fareastError);

            if (nestedObj == null || nestedObj.GetType() != typeof(CollectionObject))
            {
                throw new SyntaxErrorException(metaStrToken.Line, annotationTokens[1].value);
            }

            CollectionObject annotationObj = nestedObj as CollectionObject;
            var invalidFields = annotationObj.Collection.Where(e => !metaDataFields.Contains(e.Key)).Select(e=>e.Key).ToList();
            if (invalidFields.Count > 0)
            {
                var invalidFieldsStr = new StringBuilder();
                foreach (var field in invalidFields)
                {
                    invalidFieldsStr.AppendFormat("'{0}' ", field);
                }
                throw new SyntaxErrorException(metaStrToken.Line, invalidFields.First(),
                    string.Format("Invalid metadata field(s): {0}", invalidFieldsStr));
            }
            if (annotationObj.Collection.ContainsKey("columnrole"))
            {
                StringObject roleValue = annotationObj.Collection["columnrole"] as StringObject;

                if (string.Equals(roleValue.Value, "edge", StringComparison.OrdinalIgnoreCase))
                {
                    if (!annotationObj.Collection.ContainsKey("reference"))
                    {
                        throw new SyntaxErrorException(metaStrToken.Line, "edge", "No edge reference");
                    }

                    StringObject refValue = annotationObj.Collection["reference"] as StringObject;
                    var refTableName = new WSchemaObjectName(new Identifier { Value = refValue.Value });
                    var attributeList = new List<Tuple<Identifier, WEdgeAttributeType>>();

                    if (annotationObj.Collection.ContainsKey("attributes"))
                    {
                        CollectionObject attributeCollection = annotationObj.Collection["attributes"] as CollectionObject;

                        foreach (string propName in attributeCollection.Collection.Keys)
                        {
                            StringObject propValue = attributeCollection.Collection[propName] as StringObject;

                            attributeList.Add(new Tuple<Identifier, WEdgeAttributeType>(
                                new Identifier { Value = propName },
                                (WEdgeAttributeType)Enum.Parse(typeof(WEdgeAttributeType), propValue.Value, true)
                                ));
                        }
                    }

                    result = new WGraphTableEdgeColumn
                    {
                        ColumnName = columnName,
                        DataType = dataType,
                        TableReference = new WNamedTableReference { TableObjectName = refTableName },
                        Attributes = attributeList,
                        FirstTokenIndex = firstToken,
                        LastTokenIndex = currentToken - 1,
                    };
                }
                else if (string.Equals(roleValue.Value, "property", StringComparison.OrdinalIgnoreCase))
                {
                    if (annotationObj.Collection.Count > 1)
                    {
                        var invalidName =
                            annotationObj.Collection.Where(e => e.Key.ToLower() != "columnrole")
                                .Select(e => e.Key);
                        var sb = new StringBuilder();
                        foreach (var name in invalidName)
                        {
                            sb.AppendFormat("'{0}' ",name);
                        }
                        throw new SyntaxErrorException(metaStrToken.Line, "columnrole",
                            string.Format("Invalid metadata field(s): {0}", sb));
                    }
                    result = new WGraphTablePropertyColumn
                    {
                        ColumnName = columnName,
                        DataType = dataType,
                        FirstTokenIndex = firstToken,
                        LastTokenIndex = currentToken - 1,
                    };
                }
                else if (string.Equals(roleValue.Value, "nodeid", StringComparison.OrdinalIgnoreCase))
                {
                    if (annotationObj.Collection.Count > 1)
                    {
                        var invalidName =
                            annotationObj.Collection.Where(e => e.Key.ToLower() != "columnrole")
                                .Select(e => e.Key);
                        var sb = new StringBuilder();
                        foreach (var name in invalidName)
                        {
                            sb.AppendFormat("'{0}' ", name);
                        }
                        throw new SyntaxErrorException(metaStrToken.Line, "columnrole",
                            string.Format("Invalid metadata field(s): {0}", sb));
                    }
                    result = new WGraphTableNodeIdColumn
                    {
                        ColumnName = columnName,
                        DataType = dataType,
                        FirstTokenIndex = firstToken,
                        LastTokenIndex = currentToken - 1,
                    };
                }
                else
                {
                    throw new SyntaxErrorException(metaStrToken.Line, "columnrole", "Invalid column role");
                }
            }
            else
            {
                throw new SyntaxErrorException(metaStrToken.Line, annotationTokens[1].value, "Invalid metadata Field"); ;
            }

            nextToken = currentToken;
            return true;
        }
Esempio n. 8
0
 private static bool ParseSchemaObjectName(
     IList<TSqlParserToken> tokens,
     ref int nextToken,
     ref WSchemaObjectName result,
     ref int farestError)
 {
     var firstToken = nextToken;
     var currentToken = nextToken;
     var identifiers = new List<Identifier>();
     Identifier identifier = null;
     if (!ParseIdentifier(tokens, ref currentToken, ref identifier, ref farestError))
         return false;
     identifiers.Add(identifier);
     for (var i = 0; i < 3; ++i)
     {
         if (!ReadToken(tokens, ".", ref currentToken, ref farestError))
             break;
         ParseIdentifier(tokens, ref currentToken, ref identifier, ref farestError);
         identifiers.Add(identifier);
     }
     result = new WSchemaObjectName
     {
         Identifiers = identifiers,
         FirstTokenIndex = firstToken,
         LastTokenIndex = currentToken - 1,
     };
     nextToken = currentToken;
     return true;
 }
        /// <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;
        }
        private WMatchClause ConstructReversedMatchClause(WSelectQueryBlock node, WSqlTableContext context)
        {
            var result = new WMatchClause()
            {
                Paths = new List<WMatchPath>(),
            };

            foreach (var path in node.MatchClause.Paths)
            {
                var reversedEdgeNameList = new List<string>();
                var nodeList = new List<Tuple<WSchemaObjectName, WEdgeColumnReferenceExpression>>();
                var edgeList = path.PathEdgeList;

                for (var i = 0; i < edgeList.Count; ++i)
                {
                    var sourceTableName = edgeList[i].Item1.Identifiers.Last().Value;
                    var edgeName = edgeList[i].Item2.MultiPartIdentifier.Identifiers.Last().Value;
                    WTableReference sourceTable = context[sourceTableName];
                    var sourceTableObjectName =
                        (sourceTable as WNamedTableReference).TableObjectName.Identifiers.Last().Value;

                    reversedEdgeNameList.Add(sourceTableObjectName + "_" + edgeName + "Reversed");
                }

                var sinkIdentifier = path.Tail.Identifiers.Last();

                for (var i = edgeList.Count - 1; i >= 0; --i)
                {
                    var nodeName = new WSchemaObjectName()
                    {
                        Identifiers = new List<Identifier>
                        {
                            new Identifier()
                            {
                                Value = sinkIdentifier.Value,
                                QuoteType = sinkIdentifier.QuoteType,
                            }
                        },
                    };

                    var originalPath = edgeList[i].Item2;
                    var edgeCol = new WEdgeColumnReferenceExpression()
                    {
                        ColumnType = ColumnType.Regular,
                        Alias = originalPath.Alias,
                        MaxLength = originalPath.MaxLength,
                        MinLength = originalPath.MinLength,
                        AttributeValueDict = originalPath.AttributeValueDict,
                        MultiPartIdentifier = new WMultiPartIdentifier(new Identifier()
                        {
                            QuoteType = originalPath.MultiPartIdentifier.Identifiers.Last().QuoteType,
                            Value = reversedEdgeNameList[i],
                        }),
                    };

                    nodeList.Add(new Tuple<WSchemaObjectName, WEdgeColumnReferenceExpression>(nodeName, edgeCol));
                    sinkIdentifier = edgeList[i].Item1.Identifiers.Last();
                }

                result.Paths.Add(new WMatchPath
                                 {
                                     PathEdgeList = nodeList,
                                     Tail = edgeList[0].Item1,
                                     IsReversed = true,
                                 });
            }

            return result;
        }
Esempio n. 11
0
 internal static Tuple<string, string> SchemaNameToTuple(WSchemaObjectName name)
 {
     return
         name == null
             ? null
             : new Tuple<string, string>(
                 name.SchemaIdentifier == null
                     ? "dbo"
                     : name.SchemaIdentifier.Value.ToLower(CultureInfo.CurrentCulture),
                 name.BaseIdentifier.Value.ToLower(CultureInfo.CurrentCulture));
 }
Esempio n. 12
0
 public void AddEdgeReference(string name, WSchemaObjectName sourceNodeName, WEdgeColumnReferenceExpression edgeReference)
 {
     if (_nodeTableDictionary.ContainsKey(name) || _edgeDictionary.ContainsKey(name))
         throw new GraphViewException("Duplicate Alias");
     _edgeDictionary.Add(name,
         new Tuple<WSchemaObjectName, WEdgeColumnReferenceExpression>(sourceNodeName, edgeReference));
 }