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()); }
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)); }
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))); }
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; }
// 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); }
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; }
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; }
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)); }
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)); }